home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / UNIXTOOL / GNU / PERL / PERL5SRC.ZIP / !Perl / c / pp < prev    next >
Text File  |  1995-03-11  |  64KB  |  3,465 lines

  1. /*    pp.c
  2.  *
  3.  *    Copyright (c) 1991-1994, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  */
  9.  
  10. /*
  11.  * "It's a big house this, and very peculiar.  Always a bit more to discover,
  12.  * and no knowing what you'll find around a corner.  And Elves, sir!" --Samwise
  13.  */
  14.  
  15. #include "EXTERN.h"
  16. #include "perl.h"
  17.  
  18. static void doencodes _((SV *sv, char *s, I32 len));
  19.  
  20. /* variations on pp_null */
  21.  
  22. PP(pp_stub)
  23. {
  24.     dSP;
  25.     if (GIMME != G_ARRAY) {
  26.     XPUSHs(&sv_undef);
  27.     }
  28.     RETURN;
  29. }
  30.  
  31. PP(pp_scalar)
  32. {
  33.     return NORMAL;
  34. }
  35.  
  36. /* Pushy stuff. */
  37.  
  38. PP(pp_padav)
  39. {
  40.     dSP; dTARGET;
  41.     if (op->op_private & OPpLVAL_INTRO)
  42.     SAVECLEARSV(curpad[op->op_targ]);
  43.     EXTEND(SP, 1);
  44.     if (op->op_flags & OPf_REF) {
  45.     PUSHs(TARG);
  46.     RETURN;
  47.     }
  48.     if (GIMME == G_ARRAY) {
  49.     I32 maxarg = AvFILL((AV*)TARG) + 1;
  50.     EXTEND(SP, maxarg);
  51.     Copy(AvARRAY((AV*)TARG), SP+1, maxarg, SV*);
  52.     SP += maxarg;
  53.     }
  54.     else {
  55.     SV* sv = sv_newmortal();
  56.     I32 maxarg = AvFILL((AV*)TARG) + 1;
  57.     sv_setiv(sv, maxarg);
  58.     PUSHs(sv);
  59.     }
  60.     RETURN;
  61. }
  62.  
  63. PP(pp_padhv)
  64. {
  65.     dSP; dTARGET;
  66.     XPUSHs(TARG);
  67.     if (op->op_private & OPpLVAL_INTRO)
  68.     SAVECLEARSV(curpad[op->op_targ]);
  69.     if (op->op_flags & OPf_REF)
  70.     RETURN;
  71.     if (GIMME == G_ARRAY) { /* array wanted */
  72.     RETURNOP(do_kv(ARGS));
  73.     }
  74.     else {
  75.     SV* sv = sv_newmortal();
  76.     if (HvFILL((HV*)TARG)) {
  77.         sprintf(buf, "%d/%d", HvFILL((HV*)TARG), HvMAX((HV*)TARG)+1);
  78.         sv_setpv(sv, buf);
  79.     }
  80.     else
  81.         sv_setiv(sv, 0);
  82.     SETs(sv);
  83.     RETURN;
  84.     }
  85. }
  86.  
  87. PP(pp_padany)
  88. {
  89.     DIE("NOT IMPL LINE %d",__LINE__);
  90. }
  91.  
  92. /* Translations. */
  93.  
  94. PP(pp_rv2gv)
  95. {
  96.     dSP; dTOPss;
  97.     
  98.     if (SvROK(sv)) {
  99.       wasref:
  100.     sv = SvRV(sv);
  101.     if (SvTYPE(sv) != SVt_PVGV)
  102.         DIE("Not a GLOB reference");
  103.     }
  104.     else {
  105.     if (SvTYPE(sv) != SVt_PVGV) {
  106.         char *sym;
  107.  
  108.         if (SvGMAGICAL(sv)) {
  109.         mg_get(sv);
  110.         if (SvROK(sv))
  111.             goto wasref;
  112.         }
  113.         if (!SvOK(sv)) {
  114.         if (op->op_flags & OPf_REF ||
  115.             op->op_private & HINT_STRICT_REFS)
  116.             DIE(no_usym, "a symbol");
  117.         RETSETUNDEF;
  118.         }
  119.         sym = SvPV(sv, na);
  120.         if (op->op_private & HINT_STRICT_REFS)
  121.         DIE(no_symref, sym, "a symbol");
  122.         sv = (SV*)gv_fetchpv(sym, TRUE, SVt_PVGV);
  123.     }
  124.     }
  125.     if (op->op_private & OPpLVAL_INTRO) {
  126.     GP *ogp = GvGP(sv);
  127.  
  128.     SSCHECK(3);
  129.     SSPUSHPTR(sv);
  130.     SSPUSHPTR(ogp);
  131.     SSPUSHINT(SAVEt_GP);
  132.  
  133.     if (op->op_flags & OPf_SPECIAL) {
  134.         GvGP(sv)->gp_refcnt++;        /* will soon be assigned */
  135.         GvFLAGS(sv) |= GVf_INTRO;
  136.     }
  137.     else {
  138.         GP *gp;
  139.         Newz(602,gp, 1, GP);
  140.         GvGP(sv) = gp;
  141.         GvREFCNT(sv) = 1;
  142.         GvSV(sv) = NEWSV(72,0);
  143.         GvLINE(sv) = curcop->cop_line;
  144.         GvEGV(sv) = sv;
  145.     }
  146.     }
  147.     SETs(sv);
  148.     RETURN;
  149. }
  150.  
  151. PP(pp_sv2len)
  152. {
  153.     dSP; dTARGET;
  154.     dPOPss;
  155.     PUSHi(sv_len(sv));
  156.     RETURN;
  157. }
  158.  
  159. PP(pp_rv2sv)
  160. {
  161.     dSP; dTOPss;
  162.  
  163.     if (SvROK(sv)) {
  164.       wasref:
  165.     sv = SvRV(sv);
  166.     switch (SvTYPE(sv)) {
  167.     case SVt_PVAV:
  168.     case SVt_PVHV:
  169.     case SVt_PVCV:
  170.         DIE("Not a SCALAR reference");
  171.     }
  172.     }
  173.     else {
  174.     GV *gv = sv;
  175.     char *sym;
  176.  
  177.     if (SvTYPE(gv) != SVt_PVGV) {
  178.         if (SvGMAGICAL(sv)) {
  179.         mg_get(sv);
  180.         if (SvROK(sv))
  181.             goto wasref;
  182.         }
  183.         if (!SvOK(sv)) {
  184.         if (op->op_flags & OPf_REF ||
  185.             op->op_private & HINT_STRICT_REFS)
  186.             DIE(no_usym, "a SCALAR");
  187.         RETSETUNDEF;
  188.         }
  189.         sym = SvPV(sv, na);
  190.         if (op->op_private & HINT_STRICT_REFS)
  191.         DIE(no_symref, sym, "a SCALAR");
  192.         gv = (SV*)gv_fetchpv(sym, TRUE, SVt_PV);
  193.     }
  194.     sv = GvSV(gv);
  195.     }
  196.     if (op->op_flags & OPf_MOD) {
  197.     if (op->op_private & OPpLVAL_INTRO)
  198.         sv = save_scalar((GV*)TOPs);
  199.     else if (op->op_private & (OPpDEREF_HV|OPpDEREF_AV)) {
  200.         if (SvGMAGICAL(sv))
  201.         mg_get(sv);
  202.         if (!SvOK(sv)) {
  203.         (void)SvUPGRADE(sv, SVt_RV);
  204.         SvRV(sv) = (op->op_private & OPpDEREF_HV ?
  205.                 (SV*)newHV() : (SV*)newAV());
  206.         SvROK_on(sv);
  207.         SvSETMAGIC(sv);
  208.         }
  209.     }
  210.     }
  211.     SETs(sv);
  212.     RETURN;
  213. }
  214.  
  215. PP(pp_av2arylen)
  216. {
  217.     dSP;
  218.     AV *av = (AV*)TOPs;
  219.     SV *sv = AvARYLEN(av);
  220.     if (!sv) {
  221.     AvARYLEN(av) = sv = NEWSV(0,0);
  222.     sv_upgrade(sv, SVt_IV);
  223.     sv_magic(sv, (SV*)av, '#', Nullch, 0);
  224.     }
  225.     SETs(sv);
  226.     RETURN;
  227. }
  228.  
  229. PP(pp_pos)
  230. {
  231.     dSP; dTARGET; dPOPss;
  232.     
  233.     if (op->op_flags & OPf_MOD) {
  234.     LvTYPE(TARG) = '<';
  235.     LvTARG(TARG) = sv;
  236.     PUSHs(TARG);    /* no SvSETMAGIC */
  237.     RETURN;
  238.     }
  239.     else {
  240.     MAGIC* mg; 
  241.  
  242.     if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
  243.         mg = mg_find(sv, 'g');
  244.         if (mg && mg->mg_len >= 0) {
  245.         PUSHi(mg->mg_len + curcop->cop_arybase);
  246.         RETURN;
  247.         }
  248.     }
  249.     RETPUSHUNDEF;
  250.     }
  251. }
  252.  
  253. PP(pp_rv2cv)
  254. {
  255.     dSP;
  256.     GV *gv;
  257.     HV *stash;
  258.  
  259.     /* We always try to add a non-existent subroutine in case of AUTOLOAD. */
  260.     CV *cv = sv_2cv(TOPs, &stash, &gv, TRUE);
  261.  
  262.     SETs((SV*)cv);
  263.     RETURN;
  264. }
  265.  
  266. PP(pp_anoncode)
  267. {
  268.     dSP;
  269.     CV* cv = (CV*)cSVOP->op_sv;
  270.     EXTEND(SP,1);
  271.  
  272.     if (SvFLAGS(cv) & SVpcv_CLONE) {
  273.     cv = cv_clone(cv);
  274.     }
  275.  
  276.     PUSHs((SV*)cv);
  277.     RETURN;
  278. }
  279.  
  280. PP(pp_srefgen)
  281. {
  282.     dSP; dTOPss;
  283.     SV* rv;
  284.     rv = sv_newmortal();
  285.     sv_upgrade(rv, SVt_RV);
  286.     if (SvPADTMP(sv))
  287.     sv = newSVsv(sv);
  288.     else {
  289.     SvTEMP_off(sv);
  290.     (void)SvREFCNT_inc(sv);
  291.     }
  292.     SvRV(rv) = sv;
  293.     SvROK_on(rv);
  294.     SETs(rv);
  295.     RETURN;
  296.  
  297. PP(pp_refgen)
  298. {
  299.     dSP; dMARK;
  300.     SV* sv;
  301.     SV* rv;
  302.     if (GIMME != G_ARRAY) {
  303.     MARK[1] = *SP;
  304.     SP = MARK + 1;
  305.     }
  306.     while (MARK < SP) {
  307.     sv = *++MARK;
  308.     rv = sv_newmortal();
  309.     sv_upgrade(rv, SVt_RV);
  310.     if (SvPADTMP(sv))
  311.         sv = newSVsv(sv);
  312.     else {
  313.         SvTEMP_off(sv);
  314.         (void)SvREFCNT_inc(sv);
  315.     }
  316.     SvRV(rv) = sv;
  317.     SvROK_on(rv);
  318.     *MARK = rv;
  319.     }
  320.     RETURN;
  321. }
  322.  
  323. PP(pp_ref)
  324. {
  325.     dSP; dTARGET;
  326.     SV *sv;
  327.     char *pv;
  328.  
  329.     sv = POPs;
  330.     if (!sv || !SvROK(sv))
  331.     RETPUSHUNDEF;
  332.  
  333.     sv = SvRV(sv);
  334.     pv = sv_reftype(sv,TRUE);
  335.     PUSHp(pv, strlen(pv));
  336.     RETURN;
  337. }
  338.  
  339. PP(pp_bless)
  340. {
  341.     dSP;
  342.     HV *stash;
  343.  
  344.     if (MAXARG == 1)
  345.     stash = curcop->cop_stash;
  346.     else
  347.     stash = gv_stashsv(POPs, TRUE);
  348.  
  349.     (void)sv_bless(TOPs, stash);
  350.     RETURN;
  351. }
  352.  
  353. /* Pattern matching */
  354.  
  355. PP(pp_study)
  356. {
  357.     dSP; dTARGET;
  358.     register unsigned char *s;
  359.     register I32 pos;
  360.     register I32 ch;
  361.     register I32 *sfirst;
  362.     register I32 *snext;
  363.     I32 retval;
  364.     STRLEN len;
  365.  
  366.     s = (unsigned char*)(SvPV(TARG, len));
  367.     pos = len;
  368.     if (lastscream)
  369.     SvSCREAM_off(lastscream);
  370.     lastscream = TARG;
  371.     if (pos <= 0) {
  372.     retval = 0;
  373.     goto ret;
  374.     }
  375.     if (pos > maxscream) {
  376.     if (maxscream < 0) {
  377.         maxscream = pos + 80;
  378.         New(301, screamfirst, 256, I32);
  379.         New(302, screamnext, maxscream, I32);
  380.     }
  381.     else {
  382.         maxscream = pos + pos / 4;
  383.         Renew(screamnext, maxscream, I32);
  384.     }
  385.     }
  386.  
  387.     sfirst = screamfirst;
  388.     snext = screamnext;
  389.  
  390.     if (!sfirst || !snext)
  391.     DIE("do_study: out of memory");
  392.  
  393.     for (ch = 256; ch; --ch)
  394.     *sfirst++ = -1;
  395.     sfirst -= 256;
  396.  
  397.     while (--pos >= 0) {
  398.     ch = s[pos];
  399.     if (sfirst[ch] >= 0)
  400.         snext[pos] = sfirst[ch] - pos;
  401.     else
  402.         snext[pos] = -pos;
  403.     sfirst[ch] = pos;
  404.  
  405.     /* If there were any case insensitive searches, we must assume they
  406.      * all are.  This speeds up insensitive searches much more than
  407.      * it slows down sensitive ones.
  408.      */
  409.     if (sawi)
  410.         sfirst[fold[ch]] = pos;
  411.     }
  412.  
  413.     SvSCREAM_on(TARG);
  414.     retval = 1;
  415.   ret:
  416.     XPUSHs(sv_2mortal(newSViv((I32)retval)));
  417.     RETURN;
  418. }
  419.  
  420. PP(pp_trans)
  421. {
  422.     dSP; dTARG;
  423.     SV *sv;
  424.  
  425.     if (op->op_flags & OPf_STACKED)
  426.     sv = POPs;
  427.     else {
  428.     sv = GvSV(defgv);
  429.     EXTEND(SP,1);
  430.     }
  431.     TARG = sv_newmortal();
  432.     PUSHi(do_trans(sv, op));
  433.     RETURN;
  434. }
  435.  
  436. /* Lvalue operators. */
  437.  
  438. PP(pp_schop)
  439. {
  440.     dSP; dTARGET;
  441.     do_chop(TARG, TOPs);
  442.     SETTARG;
  443.     RETURN;
  444. }
  445.  
  446. PP(pp_chop)
  447. {
  448.     dSP; dMARK; dTARGET;
  449.     while (SP > MARK)
  450.     do_chop(TARG, POPs);
  451.     PUSHTARG;
  452.     RETURN;
  453. }
  454.  
  455. PP(pp_schomp)
  456. {
  457.     dSP; dTARGET;
  458.     SETi(do_chomp(TOPs));
  459.     RETURN;
  460. }
  461.  
  462. PP(pp_chomp)
  463. {
  464.     dSP; dMARK; dTARGET;
  465.     register I32 count = 0;
  466.     
  467.     while (SP > MARK)
  468.     count += do_chomp(POPs);
  469.     PUSHi(count);
  470.     RETURN;
  471. }
  472.  
  473. PP(pp_defined)
  474. {
  475.     dSP;
  476.     register SV* sv;
  477.  
  478.     sv = POPs;
  479.     if (!sv || !SvANY(sv))
  480.     RETPUSHNO;
  481.     switch (SvTYPE(sv)) {
  482.     case SVt_PVAV:
  483.     if (AvMAX(sv) >= 0)
  484.         RETPUSHYES;
  485.     break;
  486.     case SVt_PVHV:
  487.     if (HvARRAY(sv))
  488.         RETPUSHYES;
  489.     break;
  490.     case SVt_PVCV:
  491.     if (CvROOT(sv) || CvXSUB(sv))
  492.         RETPUSHYES;
  493.     break;
  494.     default:
  495.     if (SvGMAGICAL(sv))
  496.         mg_get(sv);
  497.     if (SvOK(sv))
  498.         RETPUSHYES;
  499.     }
  500.     RETPUSHNO;
  501. }
  502.  
  503. PP(pp_undef)
  504. {
  505.     dSP;
  506.     SV *sv;
  507.  
  508.     if (!op->op_private)
  509.     RETPUSHUNDEF;
  510.  
  511.     sv = POPs;
  512.     if (!sv)
  513.     RETPUSHUNDEF;
  514.  
  515.     if (SvTHINKFIRST(sv)) {
  516.     if (SvREADONLY(sv))
  517.         RETPUSHUNDEF;
  518.     if (SvROK(sv))
  519.         sv_unref(sv);
  520.     }
  521.  
  522.     switch (SvTYPE(sv)) {
  523.     case SVt_NULL:
  524.     break;
  525.     case SVt_PVAV:
  526.     av_undef((AV*)sv);
  527.     break;
  528.     case SVt_PVHV:
  529.     hv_undef((HV*)sv);
  530.     break;
  531.     case SVt_PVCV:
  532.     cv_undef((CV*)sv);
  533.     sub_generation++;
  534.     break;
  535.     default:
  536.     if (sv != GvSV(defgv)) {
  537.         if (SvPOK(sv) && SvLEN(sv)) {
  538.         (void)SvOOK_off(sv);
  539.         Safefree(SvPVX(sv));
  540.         SvPV_set(sv, Nullch);
  541.         SvLEN_set(sv, 0);
  542.         }
  543.         (void)SvOK_off(sv);
  544.         SvSETMAGIC(sv);
  545.     }
  546.     }
  547.  
  548.     RETPUSHUNDEF;
  549. }
  550.  
  551. PP(pp_predec)
  552. {
  553.     dSP;
  554.     if (SvIOK(TOPs)) {
  555.     --SvIVX(TOPs);
  556.     SvFLAGS(TOPs) &= ~(SVf_NOK|SVf_POK|SVp_NOK|SVp_POK);
  557.     }
  558.     else
  559.     sv_dec(TOPs);
  560.     SvSETMAGIC(TOPs);
  561.     return NORMAL;
  562. }
  563.  
  564. PP(pp_postinc)
  565. {
  566.     dSP; dTARGET;
  567.     sv_setsv(TARG, TOPs);
  568.     if (SvIOK(TOPs)) {
  569.     ++SvIVX(TOPs);
  570.     SvFLAGS(TOPs) &= ~(SVf_NOK|SVf_POK|SVp_NOK|SVp_POK);
  571.     }
  572.     else
  573.     sv_inc(TOPs);
  574.     SvSETMAGIC(TOPs);
  575.     if (!SvOK(TARG))
  576.     sv_setiv(TARG, 0);
  577.     SETs(TARG);
  578.     return NORMAL;
  579. }
  580.  
  581. PP(pp_postdec)
  582. {
  583.     dSP; dTARGET;
  584.     sv_setsv(TARG, TOPs);
  585.     if (SvIOK(TOPs)) {
  586.     --SvIVX(TOPs);
  587.     SvFLAGS(TOPs) &= ~(SVf_NOK|SVf_POK|SVp_NOK|SVp_POK);
  588.     }
  589.     else
  590.     sv_dec(TOPs);
  591.     SvSETMAGIC(TOPs);
  592.     SETs(TARG);
  593.     return NORMAL;
  594. }
  595.  
  596. /* Ordinary operators. */
  597.  
  598. PP(pp_pow)
  599. {
  600.     dSP; dATARGET; tryAMAGICbin(pow,opASSIGN); 
  601.     {
  602.       dPOPTOPnnrl;
  603.       SETn( pow( left, right) );
  604.       RETURN;
  605.     }
  606. }
  607.  
  608. PP(pp_multiply)
  609. {
  610.     dSP; dATARGET; tryAMAGICbin(mult,opASSIGN); 
  611.     {
  612.       dPOPTOPnnrl;
  613.       SETn( left * right );
  614.       RETURN;
  615.     }
  616. }
  617.  
  618. PP(pp_divide)
  619. {
  620.     dSP; dATARGET; tryAMAGICbin(div,opASSIGN); 
  621.     {
  622.       dPOPnv;
  623.       if (value == 0.0)
  624.     DIE("Illegal division by zero");
  625. #ifdef SLOPPYDIVIDE
  626.       /* insure that 20./5. == 4. */
  627.       {
  628.     double x;
  629.     I32    k;
  630.     x =  POPn;
  631.     if ((double)I_32(x)     == x &&
  632.         (double)I_32(value) == value &&
  633.         (k = I_32(x)/I_32(value))*I_32(value) == I_32(x)) {
  634.         value = k;
  635.     } else {
  636.         value = x/value;
  637.     }
  638.       }
  639. #else
  640.       value = POPn / value;
  641. #endif
  642.       PUSHn( value );
  643.       RETURN;
  644.     }
  645. }
  646.  
  647. PP(pp_modulo)
  648. {
  649.     dSP; dATARGET; tryAMAGICbin(mod,opASSIGN);
  650.     {
  651.       register unsigned long tmpulong;
  652.       register long tmplong;
  653.       I32 value;
  654.  
  655.       tmpulong = (unsigned long) POPn;
  656.       if (tmpulong == 0L)
  657.     DIE("Illegal modulus zero");
  658.       value = TOPn;
  659.       if (value >= 0.0)
  660.     value = (I32)(((unsigned long)value) % tmpulong);
  661.       else {
  662.     tmplong = (long)value;
  663.     value = (I32)(tmpulong - ((-tmplong - 1) % tmpulong)) - 1;
  664.       }
  665.       SETi(value);
  666.       RETURN;
  667.     }
  668. }
  669.  
  670. PP(pp_repeat)
  671. {
  672.   dSP; dATARGET; tryAMAGICbin(repeat,opASSIGN);
  673.   {
  674.     register I32 count = POPi;
  675.     if (GIMME == G_ARRAY && op->op_private & OPpREPEAT_DOLIST) {
  676.     dMARK;
  677.     I32 items = SP - MARK;
  678.     I32 max;
  679.  
  680.     max = items * count;
  681.     MEXTEND(MARK, max);
  682.     if (count > 1) {
  683.         while (SP > MARK) {
  684.         if (*SP)
  685.             SvTEMP_off((*SP));
  686.         SP--;
  687.         }
  688.         MARK++;
  689.         repeatcpy((char*)(MARK + items), (char*)MARK,
  690.         items * sizeof(SV*), count - 1);
  691.         SP += max;
  692.     }
  693.     else if (count <= 0)
  694.         SP -= items;
  695.     }
  696.     else {    /* Note: mark already snarfed by pp_list */
  697.     SV *tmpstr;
  698.     STRLEN len;
  699.  
  700.     tmpstr = POPs;
  701.     if (TARG == tmpstr && SvTHINKFIRST(tmpstr)) {
  702.         if (SvREADONLY(tmpstr) && curcop != &compiling)
  703.         DIE("Can't x= to readonly value");
  704.         if (SvROK(tmpstr))
  705.         sv_unref(tmpstr);
  706.     }
  707.     SvSetSV(TARG, tmpstr);
  708.     SvPV_force(TARG, len);
  709.     if (count >= 1) {
  710.         SvGROW(TARG, (count * len) + 1);
  711.         if (count > 1)
  712.         repeatcpy(SvPVX(TARG) + len, SvPVX(TARG), len, count - 1);
  713.         SvCUR(TARG) *= count;
  714.         *SvEND(TARG) = '\0';
  715.         (void)SvPOK_only(TARG);
  716.     }
  717.     else
  718.         sv_setsv(TARG, &sv_no);
  719.     PUSHTARG;
  720.     }
  721.     RETURN;
  722.   }
  723. }
  724.  
  725. PP(pp_subtract)
  726. {
  727.     dSP; dATARGET; tryAMAGICbin(subtr,opASSIGN); 
  728.     {
  729.       dPOPTOPnnrl;
  730.       SETn( left - right );
  731.       RETURN;
  732.     }
  733. }
  734.  
  735. PP(pp_left_shift)
  736. {
  737.     dSP; dATARGET; tryAMAGICbin(lshift,opASSIGN); 
  738.     {
  739.         dPOPTOPiirl;
  740.         SETi( left << right );
  741.         RETURN;
  742.     }
  743. }
  744.  
  745. PP(pp_right_shift)
  746. {
  747.     dSP; dATARGET; tryAMAGICbin(rshift,opASSIGN); 
  748.     {
  749.       dPOPTOPiirl;
  750.       SETi( left >> right );
  751.       RETURN;
  752.     }
  753. }
  754.  
  755. PP(pp_lt)
  756. {
  757.     dSP; tryAMAGICbinSET(lt,0); 
  758.     {
  759.       dPOPnv;
  760.       SETs((TOPn < value) ? &sv_yes : &sv_no);
  761.       RETURN;
  762.     }
  763. }
  764.  
  765. PP(pp_gt)
  766. {
  767.     dSP; tryAMAGICbinSET(gt,0); 
  768.     {
  769.       dPOPnv;
  770.       SETs((TOPn > value) ? &sv_yes : &sv_no);
  771.       RETURN;
  772.     }
  773. }
  774.  
  775. PP(pp_le)
  776. {
  777.     dSP; tryAMAGICbinSET(le,0); 
  778.     {
  779.       dPOPnv;
  780.       SETs((TOPn <= value) ? &sv_yes : &sv_no);
  781.       RETURN;
  782.     }
  783. }
  784.  
  785. PP(pp_ge)
  786. {
  787.     dSP; tryAMAGICbinSET(ge,0); 
  788.     {
  789.       dPOPnv;
  790.       SETs((TOPn >= value) ? &sv_yes : &sv_no);
  791.       RETURN;
  792.     }
  793. }
  794.  
  795. PP(pp_ne)
  796. {
  797.     dSP; tryAMAGICbinSET(ne,0); 
  798.     {
  799.       dPOPnv;
  800.       SETs((TOPn != value) ? &sv_yes : &sv_no);
  801.       RETURN;
  802.     }
  803. }
  804.  
  805. PP(pp_ncmp)
  806. {
  807.     dSP; dTARGET; tryAMAGICbin(ncmp,0); 
  808.     {
  809.       dPOPTOPnnrl;
  810.       I32 value;
  811.  
  812.       if (left > right)
  813.     value = 1;
  814.       else if (left < right)
  815.     value = -1;
  816.       else
  817.     value = 0;
  818.       SETi(value);
  819.       RETURN;
  820.     }
  821. }
  822.  
  823. PP(pp_slt)
  824. {
  825.     dSP; tryAMAGICbinSET(slt,0); 
  826.     {
  827.       dPOPTOPssrl;
  828.       SETs( sv_cmp(left, right) < 0 ? &sv_yes : &sv_no );
  829.       RETURN;
  830.     }
  831. }
  832.  
  833. PP(pp_sgt)
  834. {
  835.     dSP; tryAMAGICbinSET(sgt,0); 
  836.     {
  837.       dPOPTOPssrl;
  838.       SETs( sv_cmp(left, right) > 0 ? &sv_yes : &sv_no );
  839.       RETURN;
  840.     }
  841. }
  842.  
  843. PP(pp_sle)
  844. {
  845.     dSP; tryAMAGICbinSET(sle,0); 
  846.     {
  847.       dPOPTOPssrl;
  848.       SETs( sv_cmp(left, right) <= 0 ? &sv_yes : &sv_no );
  849.       RETURN;
  850.     }
  851. }
  852.  
  853. PP(pp_sge)
  854. {
  855.     dSP; tryAMAGICbinSET(sge,0); 
  856.     {
  857.       dPOPTOPssrl;
  858.       SETs( sv_cmp(left, right) >= 0 ? &sv_yes : &sv_no );
  859.       RETURN;
  860.     }
  861. }
  862.  
  863. PP(pp_sne)
  864. {
  865.     dSP; tryAMAGICbinSET(sne,0); 
  866.     {
  867.       dPOPTOPssrl;
  868.       SETs( !sv_eq(left, right) ? &sv_yes : &sv_no );
  869.       RETURN;
  870.     }
  871. }
  872.  
  873. PP(pp_scmp)
  874. {
  875.     dSP; dTARGET;  tryAMAGICbin(scmp,0);
  876.     {
  877.       dPOPTOPssrl;
  878.       SETi( sv_cmp(left, right) );
  879.       RETURN;
  880.     }
  881. }
  882.  
  883. PP(pp_bit_and) {
  884.     dSP; dATARGET; tryAMAGICbin(band,opASSIGN); 
  885.     {
  886.       dPOPTOPssrl;
  887.       if (SvNIOK(left) || SvNIOK(right)) {
  888.     unsigned long value = U_L(SvNV(left));
  889.     value = value & U_L(SvNV(right));
  890.     SETn((double)value);
  891.       }
  892.       else {
  893.     do_vop(op->op_type, TARG, left, right);
  894.     SETTARG;
  895.       }
  896.       RETURN;
  897.     }
  898. }
  899.  
  900. PP(pp_bit_xor)
  901. {
  902.     dSP; dATARGET; tryAMAGICbin(bxor,opASSIGN); 
  903.     {
  904.       dPOPTOPssrl;
  905.       if (SvNIOK(left) || SvNIOK(right)) {
  906.     unsigned long value = U_L(SvNV(left));
  907.     value = value ^ U_L(SvNV(right));
  908.     SETn((double)value);
  909.       }
  910.       else {
  911.     do_vop(op->op_type, TARG, left, right);
  912.     SETTARG;
  913.       }
  914.       RETURN;
  915.     }
  916. }
  917.  
  918. PP(pp_bit_or)
  919. {
  920.     dSP; dATARGET; tryAMAGICbin(bor,opASSIGN); 
  921.     {
  922.       dPOPTOPssrl;
  923.       if (SvNIOK(left) || SvNIOK(right)) {
  924.     unsigned long value = U_L(SvNV(left));
  925.     value = value | U_L(SvNV(right));
  926.     SETn((double)value);
  927.       }
  928.       else {
  929.     do_vop(op->op_type, TARG, left, right);
  930.     SETTARG;
  931.       }
  932.       RETURN;
  933.     }
  934. }
  935.  
  936. PP(pp_negate)
  937. {
  938.     dSP; dTARGET; tryAMAGICun(neg);
  939.     {
  940.     dTOPss;
  941.     if (SvNIOK(sv))
  942.         SETn(-SvNV(sv));
  943.     else if (SvPOK(sv)) {
  944.         STRLEN len;
  945.         char *s = SvPV(sv, len);
  946.         if (isALPHA(*s) || *s == '_') {
  947.         sv_setpvn(TARG, "-", 1);
  948.         sv_catsv(TARG, sv);
  949.         }
  950.         else if (*s == '+' || *s == '-') {
  951.         sv_setsv(TARG, sv);
  952.         *SvPV_force(TARG, len) = *s == '-' ? '+' : '-';
  953.         }
  954.         else
  955.         sv_setnv(TARG, -SvNV(sv));
  956.         SETTARG;
  957.     }
  958.     }
  959.     RETURN;
  960. }
  961.  
  962. PP(pp_not)
  963. {
  964. #ifdef OVERLOAD
  965.     dSP; tryAMAGICunSET(not);
  966. #endif /* OVERLOAD */
  967.     *stack_sp = SvTRUE(*stack_sp) ? &sv_no : &sv_yes;
  968.     return NORMAL;
  969. }
  970.  
  971. PP(pp_complement)
  972. {
  973.     dSP; dTARGET; tryAMAGICun(compl); 
  974.     {
  975.       dTOPss;
  976.       register I32 anum;
  977.  
  978.       if (SvNIOK(sv)) {
  979.     IV iv = ~SvIV(sv);
  980.     if (iv < 0)
  981.         SETn( (double) ~U_L(SvNV(sv)) );
  982.     else
  983.         SETi( iv );
  984.       }
  985.       else {
  986.     register char *tmps;
  987.     register long *tmpl;
  988.     STRLEN len;
  989.  
  990.     SvSetSV(TARG, sv);
  991.     tmps = SvPV_force(TARG, len);
  992.     anum = len;
  993. #ifdef LIBERAL
  994.     for ( ; anum && (unsigned long)tmps % sizeof(long); anum--, tmps++)
  995.         *tmps = ~*tmps;
  996.     tmpl = (long*)tmps;
  997.     for ( ; anum >= sizeof(long); anum -= sizeof(long), tmpl++)
  998.         *tmpl = ~*tmpl;
  999.     tmps = (char*)tmpl;
  1000. #endif
  1001.     for ( ; anum > 0; anum--, tmps++)
  1002.         *tmps = ~*tmps;
  1003.  
  1004.     SETs(TARG);
  1005.       }
  1006.       RETURN;
  1007.     }
  1008. }
  1009.  
  1010. /* integer versions of some of the above */
  1011.  
  1012. PP(pp_i_multiply)
  1013. {
  1014.     dSP; dATARGET; tryAMAGICbin(mult,opASSIGN); 
  1015.     {
  1016.       dPOPTOPiirl;
  1017.       SETi( left * right );
  1018.       RETURN;
  1019.     }
  1020. }
  1021.  
  1022. PP(pp_i_divide)
  1023. {
  1024.     dSP; dATARGET; tryAMAGICbin(div,opASSIGN); 
  1025.     {
  1026.       dPOPiv;
  1027.       if (value == 0)
  1028.     DIE("Illegal division by zero");
  1029.       value = POPi / value;
  1030.       PUSHi( value );
  1031.       RETURN;
  1032.     }
  1033. }
  1034.  
  1035. PP(pp_i_modulo)
  1036. {
  1037.     dSP; dATARGET; tryAMAGICbin(mod,opASSIGN); 
  1038.     {
  1039.       dPOPTOPiirl;
  1040.       SETi( left % right );
  1041.       RETURN;
  1042.     }
  1043. }
  1044.  
  1045. PP(pp_i_add)
  1046. {
  1047.     dSP; dATARGET; tryAMAGICbin(add,opASSIGN); 
  1048.     {
  1049.       dPOPTOPiirl;
  1050.       SETi( left + right );
  1051.       RETURN;
  1052.     }
  1053. }
  1054.  
  1055. PP(pp_i_subtract)
  1056. {
  1057.     dSP; dATARGET; tryAMAGICbin(subtr,opASSIGN); 
  1058.     {
  1059.       dPOPTOPiirl;
  1060.       SETi( left - right );
  1061.       RETURN;
  1062.     }
  1063. }
  1064.  
  1065. PP(pp_i_lt)
  1066. {
  1067.     dSP; tryAMAGICbinSET(lt,0); 
  1068.     {
  1069.       dPOPTOPiirl;
  1070.       SETs((left < right) ? &sv_yes : &sv_no);
  1071.       RETURN;
  1072.     }
  1073. }
  1074.  
  1075. PP(pp_i_gt)
  1076. {
  1077.     dSP; tryAMAGICbinSET(gt,0); 
  1078.     {
  1079.       dPOPTOPiirl;
  1080.       SETs((left > right) ? &sv_yes : &sv_no);
  1081.       RETURN;
  1082.     }
  1083. }
  1084.  
  1085. PP(pp_i_le)
  1086. {
  1087.     dSP; tryAMAGICbinSET(le,0); 
  1088.     {
  1089.       dPOPTOPiirl;
  1090.       SETs((left <= right) ? &sv_yes : &sv_no);
  1091.       RETURN;
  1092.     }
  1093. }
  1094.  
  1095. PP(pp_i_ge)
  1096. {
  1097.     dSP; tryAMAGICbinSET(ge,0); 
  1098.     {
  1099.       dPOPTOPiirl;
  1100.       SETs((left >= right) ? &sv_yes : &sv_no);
  1101.       RETURN;
  1102.     }
  1103. }
  1104.  
  1105. PP(pp_i_eq)
  1106. {
  1107.     dSP; tryAMAGICbinSET(eq,0); 
  1108.     {
  1109.       dPOPTOPiirl;
  1110.       SETs((left == right) ? &sv_yes : &sv_no);
  1111.       RETURN;
  1112.     }
  1113. }
  1114.  
  1115. PP(pp_i_ne)
  1116. {
  1117.     dSP; tryAMAGICbinSET(ne,0); 
  1118.     {
  1119.       dPOPTOPiirl;
  1120.       SETs((left != right) ? &sv_yes : &sv_no);
  1121.       RETURN;
  1122.     }
  1123. }
  1124.  
  1125. PP(pp_i_ncmp)
  1126. {
  1127.     dSP; dTARGET; tryAMAGICbin(ncmp,0); 
  1128.     {
  1129.       dPOPTOPiirl;
  1130.       I32 value;
  1131.  
  1132.       if (left > right)
  1133.     value = 1;
  1134.       else if (left < right)
  1135.     value = -1;
  1136.       else
  1137.     value = 0;
  1138.       SETi(value);
  1139.       RETURN;
  1140.     }
  1141. }
  1142.  
  1143. PP(pp_i_negate)
  1144. {
  1145.     dSP; dTARGET; tryAMAGICun(neg);
  1146.     SETi(-TOPi);
  1147.     RETURN;
  1148. }
  1149.  
  1150. /* High falutin' math. */
  1151.  
  1152. PP(pp_atan2)
  1153. {
  1154.     dSP; dTARGET; tryAMAGICbin(atan2,0); 
  1155.     {
  1156.       dPOPTOPnnrl;
  1157.       SETn(atan2(left, right));
  1158.       RETURN;
  1159.     }
  1160. }
  1161.  
  1162. PP(pp_sin)
  1163. {
  1164.     dSP; dTARGET; tryAMAGICun(sin);
  1165.     {
  1166.       double value;
  1167.       value = POPn;
  1168.       value = sin(value);
  1169.       XPUSHn(value);
  1170.       RETURN;
  1171.     }
  1172. }
  1173.  
  1174. PP(pp_cos)
  1175. {
  1176.     dSP; dTARGET; tryAMAGICun(cos);
  1177.     {
  1178.       double value;
  1179.       value = POPn;
  1180.       value = cos(value);
  1181.       XPUSHn(value);
  1182.       RETURN;
  1183.     }
  1184. }
  1185.  
  1186. PP(pp_rand)
  1187. {
  1188.     dSP; dTARGET;
  1189.     double value;
  1190.     if (MAXARG < 1)
  1191.     value = 1.0;
  1192.     else
  1193.     value = POPn;
  1194.     if (value == 0.0)
  1195.     value = 1.0;
  1196. #if RANDBITS == 31
  1197.     value = rand() * value / 2147483648.0;
  1198. #else
  1199. #if RANDBITS == 16
  1200.     value = rand() * value / 65536.0;
  1201. #else
  1202. #if RANDBITS == 15
  1203.     value = rand() * value / 32768.0;
  1204. #else
  1205.     value = rand() * value / (double)(((unsigned long)1) << RANDBITS);
  1206. #endif
  1207. #endif
  1208. #endif
  1209.     XPUSHn(value);
  1210.     RETURN;
  1211. }
  1212.  
  1213. PP(pp_srand)
  1214. {
  1215.     dSP;
  1216.     I32 anum;
  1217.     Time_t when;
  1218.  
  1219.     if (MAXARG < 1) {
  1220.     (void)time(&when);
  1221.     anum = when;
  1222.     }
  1223.     else
  1224.     anum = POPi;
  1225.     (void)srand(anum);
  1226.     EXTEND(SP, 1);
  1227.     RETPUSHYES;
  1228. }
  1229.  
  1230. PP(pp_exp)
  1231. {
  1232.     dSP; dTARGET; tryAMAGICun(exp);
  1233.     {
  1234.       double value;
  1235.       value = POPn;
  1236.       value = exp(value);
  1237.       XPUSHn(value);
  1238.       RETURN;
  1239.     }
  1240. }
  1241.  
  1242. PP(pp_log)
  1243. {
  1244.     dSP; dTARGET; tryAMAGICun(log);
  1245.     {
  1246.       double value;
  1247.       value = POPn;
  1248.       if (value <= 0.0)
  1249.     DIE("Can't take log of %g", value);
  1250.       value = log(value);
  1251.       XPUSHn(value);
  1252.       RETURN;
  1253.     }
  1254. }
  1255.  
  1256. PP(pp_sqrt)
  1257. {
  1258.     dSP; dTARGET; tryAMAGICun(sqrt);
  1259.     {
  1260.       double value;
  1261.       value = POPn;
  1262.       if (value < 0.0)
  1263.     DIE("Can't take sqrt of %g", value);
  1264.       value = sqrt(value);
  1265.       XPUSHn(value);
  1266.       RETURN;
  1267.     }
  1268. }
  1269.  
  1270. PP(pp_int)
  1271. {
  1272.     dSP; dTARGET;
  1273.     double value;
  1274.     value = POPn;
  1275.     if (value >= 0.0)
  1276.     (void)modf(value, &value);
  1277.     else {
  1278.     (void)modf(-value, &value);
  1279.     value = -value;
  1280.     }
  1281.     XPUSHn(value);
  1282.     RETURN;
  1283. }
  1284.  
  1285. PP(pp_abs)
  1286. {
  1287.     dSP; dTARGET; tryAMAGICun(abs);
  1288.     {
  1289.       double value;
  1290.       value = POPn;
  1291.  
  1292.       if (value < 0.0)
  1293.     value = -value;
  1294.  
  1295.       XPUSHn(value);
  1296.       RETURN;
  1297.     }
  1298. }
  1299.  
  1300. PP(pp_hex)
  1301. {
  1302.     dSP; dTARGET;
  1303.     char *tmps;
  1304.     I32 argtype;
  1305.  
  1306.     tmps = POPp;
  1307.     XPUSHi( scan_hex(tmps, 99, &argtype) );
  1308.     RETURN;
  1309. }
  1310.  
  1311. PP(pp_oct)
  1312. {
  1313.     dSP; dTARGET;
  1314.     I32 value;
  1315.     I32 argtype;
  1316.     char *tmps;
  1317.  
  1318.     tmps = POPp;
  1319.     while (*tmps && (isSPACE(*tmps) || *tmps == '0'))
  1320.     tmps++;
  1321.     if (*tmps == 'x')
  1322.     value = (I32)scan_hex(++tmps, 99, &argtype);
  1323.     else
  1324.     value = (I32)scan_oct(tmps, 99, &argtype);
  1325.     XPUSHi(value);
  1326.     RETURN;
  1327. }
  1328.  
  1329. /* String stuff. */
  1330.  
  1331. PP(pp_length)
  1332. {
  1333.     dSP; dTARGET;
  1334.     SETi( sv_len(TOPs) );
  1335.     RETURN;
  1336. }
  1337.  
  1338. PP(pp_substr)
  1339. {
  1340.     dSP; dTARGET;
  1341.     SV *sv;
  1342.     I32 len;
  1343.     STRLEN curlen;
  1344.     I32 pos;
  1345.     I32 rem;
  1346.     I32 lvalue = op->op_flags & OPf_MOD;
  1347.     char *tmps;
  1348.     I32 arybase = curcop->cop_arybase;
  1349.  
  1350.     if (MAXARG > 2)
  1351.     len = POPi;
  1352.     pos = POPi - arybase;
  1353.     sv = POPs;
  1354.     tmps = SvPV(sv, curlen);
  1355.     if (pos < 0)
  1356.     pos += curlen + arybase;
  1357.     if (pos < 0 || pos > curlen) {
  1358.     if (dowarn || lvalue)
  1359.         warn("substr outside of string");
  1360.     RETPUSHUNDEF;
  1361.     }
  1362.     else {
  1363.     if (MAXARG < 3)
  1364.         len = curlen;
  1365.     else if (len < 0) {
  1366.         len += curlen - pos;
  1367.         if (len < 0)
  1368.         len = 0;
  1369.     }
  1370.     tmps += pos;
  1371.     rem = curlen - pos;    /* rem=how many bytes left*/
  1372.     if (rem > len)
  1373.         rem = len;
  1374.     sv_setpvn(TARG, tmps, rem);
  1375.     if (lvalue) {            /* it's an lvalue! */
  1376.         (void)SvPOK_only(sv);
  1377.         if (SvTYPE(TARG) < SVt_PVLV) {
  1378.         sv_upgrade(TARG, SVt_PVLV);
  1379.         sv_magic(TARG, Nullsv, 'x', Nullch, 0);
  1380.         }
  1381.  
  1382.         LvTYPE(TARG) = 's';
  1383.         LvTARG(TARG) = sv;
  1384.         LvTARGOFF(TARG) = pos;
  1385.         LvTARGLEN(TARG) = rem; 
  1386.     }
  1387.     }
  1388.     PUSHs(TARG);        /* avoid SvSETMAGIC here */
  1389.     RETURN;
  1390. }
  1391.  
  1392. PP(pp_vec)
  1393. {
  1394.     dSP; dTARGET;
  1395.     register I32 size = POPi;
  1396.     register I32 offset = POPi;
  1397.     register SV *src = POPs;
  1398.     I32 lvalue = op->op_flags & OPf_MOD;
  1399.     STRLEN srclen;
  1400.     unsigned char *s = (unsigned char*)SvPV(src, srclen);
  1401.     unsigned long retnum;
  1402.     I32 len;
  1403.  
  1404.     offset *= size;        /* turn into bit offset */
  1405.     len = (offset + size + 7) / 8;
  1406.     if (offset < 0 || size < 1)
  1407.     retnum = 0;
  1408.     else {
  1409.     if (lvalue) {                      /* it's an lvalue! */
  1410.         if (SvTYPE(TARG) < SVt_PVLV) {
  1411.         sv_upgrade(TARG, SVt_PVLV);
  1412.         sv_magic(TARG, Nullsv, 'v', Nullch, 0);
  1413.         }
  1414.  
  1415.         LvTYPE(TARG) = 'v';
  1416.         LvTARG(TARG) = src;
  1417.         LvTARGOFF(TARG) = offset; 
  1418.         LvTARGLEN(TARG) = size; 
  1419.     }
  1420.     if (len > srclen) {
  1421.         if (size <= 8)
  1422.         retnum = 0;
  1423.         else {
  1424.         offset >>= 3;
  1425.         if (size == 16) {
  1426.             if (offset >= srclen)
  1427.             retnum = 0;
  1428.             else
  1429.             retnum = (unsigned long) s[offset] << 8;
  1430.         }
  1431.         else if (size == 32) {
  1432.             if (offset >= srclen)
  1433.             retnum = 0;
  1434.             else if (offset + 1 >= srclen)
  1435.             retnum = (unsigned long) s[offset] << 24;
  1436.             else if (offset + 2 >= srclen)
  1437.             retnum = ((unsigned long) s[offset] << 24) +
  1438.                 ((unsigned long) s[offset + 1] << 16);
  1439.             else
  1440.             retnum = ((unsigned long) s[offset] << 24) +
  1441.                 ((unsigned long) s[offset + 1] << 16) +
  1442.                 (s[offset + 2] << 8);
  1443.         }
  1444.         }
  1445.     }
  1446.     else if (size < 8)
  1447.         retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
  1448.     else {
  1449.         offset >>= 3;
  1450.         if (size == 8)
  1451.         retnum = s[offset];
  1452.         else if (size == 16)
  1453.         retnum = ((unsigned long) s[offset] << 8) + s[offset+1];
  1454.         else if (size == 32)
  1455.         retnum = ((unsigned long) s[offset] << 24) +
  1456.             ((unsigned long) s[offset + 1] << 16) +
  1457.             (s[offset + 2] << 8) + s[offset+3];
  1458.     }
  1459.     }
  1460.  
  1461.     sv_setiv(TARG, (I32)retnum);
  1462.     PUSHs(TARG);
  1463.     RETURN;
  1464. }
  1465.  
  1466. PP(pp_index)
  1467. {
  1468.     dSP; dTARGET;
  1469.     SV *big;
  1470.     SV *little;
  1471.     I32 offset;
  1472.     I32 retval;
  1473.     char *tmps;
  1474.     char *tmps2;
  1475.     STRLEN biglen;
  1476.     I32 arybase = curcop->cop_arybase;
  1477.  
  1478.     if (MAXARG < 3)
  1479.     offset = 0;
  1480.     else
  1481.     offset = POPi - arybase;
  1482.     little = POPs;
  1483.     big = POPs;
  1484.     tmps = SvPV(big, biglen);
  1485.     if (offset < 0)
  1486.     offset = 0;
  1487.     else if (offset > biglen)
  1488.     offset = biglen;
  1489.     if (!(tmps2 = fbm_instr((unsigned char*)tmps + offset,
  1490.       (unsigned char*)tmps + biglen, little)))
  1491.     retval = -1 + arybase;
  1492.     else
  1493.     retval = tmps2 - tmps + arybase;
  1494.     PUSHi(retval);
  1495.     RETURN;
  1496. }
  1497.  
  1498. PP(pp_rindex)
  1499. {
  1500.     dSP; dTARGET;
  1501.     SV *big;
  1502.     SV *little;
  1503.     STRLEN blen;
  1504.     STRLEN llen;
  1505.     SV *offstr;
  1506.     I32 offset;
  1507.     I32 retval;
  1508.     char *tmps;
  1509.     char *tmps2;
  1510.     I32 arybase = curcop->cop_arybase;
  1511.  
  1512.     if (MAXARG >= 3)
  1513.     offstr = POPs;
  1514.     little = POPs;
  1515.     big = POPs;
  1516.     tmps2 = SvPV(little, llen);
  1517.     tmps = SvPV(big, blen);
  1518.     if (MAXARG < 3)
  1519.     offset = blen;
  1520.     else
  1521.     offset = SvIV(offstr) - arybase + llen;
  1522.     if (offset < 0)
  1523.     offset = 0;
  1524.     else if (offset > blen)
  1525.     offset = blen;
  1526.     if (!(tmps2 = rninstr(tmps,  tmps  + offset,
  1527.               tmps2, tmps2 + llen)))
  1528.     retval = -1 + arybase;
  1529.     else
  1530.     retval = tmps2 - tmps + arybase;
  1531.     PUSHi(retval);
  1532.     RETURN;
  1533. }
  1534.  
  1535. PP(pp_sprintf)
  1536. {
  1537.     dSP; dMARK; dORIGMARK; dTARGET;
  1538.     do_sprintf(TARG, SP-MARK, MARK+1);
  1539.     SP = ORIGMARK;
  1540.     PUSHTARG;
  1541.     RETURN;
  1542. }
  1543.  
  1544. PP(pp_ord)
  1545. {
  1546.     dSP; dTARGET;
  1547.     I32 value;
  1548.     char *tmps;
  1549.  
  1550. #ifndef I286
  1551.     tmps = POPp;
  1552.     value = (I32) (*tmps & 255);
  1553. #else
  1554.     I32 anum;
  1555.     tmps = POPp;
  1556.     anum = (I32) *tmps;
  1557.     value = (I32) (anum & 255);
  1558. #endif
  1559.     XPUSHi(value);
  1560.     RETURN;
  1561. }
  1562.  
  1563. PP(pp_chr)
  1564. {
  1565.     dSP; dTARGET;
  1566.     char *tmps;
  1567.  
  1568.     (void)SvUPGRADE(TARG,SVt_PV);
  1569.     SvGROW(TARG,2);
  1570.     SvCUR_set(TARG, 1);
  1571.     tmps = SvPVX(TARG);
  1572.     *tmps++ = POPi;
  1573.     *tmps = '\0';
  1574.     (void)SvPOK_only(TARG);
  1575.     XPUSHs(TARG);
  1576.     RETURN;
  1577. }
  1578.  
  1579. PP(pp_crypt)
  1580. {
  1581.     dSP; dTARGET; dPOPTOPssrl;
  1582. #ifdef HAS_CRYPT
  1583.     char *tmps = SvPV(left, na);
  1584. #ifdef FCRYPT
  1585.     sv_setpv(TARG, fcrypt(tmps, SvPV(right, na)));
  1586. #else
  1587.     sv_setpv(TARG, crypt(tmps, SvPV(right, na)));
  1588. #endif
  1589. #else
  1590.     DIE(
  1591.       "The crypt() function is unimplemented due to excessive paranoia.");
  1592. #endif
  1593.     SETs(TARG);
  1594.     RETURN;
  1595. }
  1596.  
  1597. PP(pp_ucfirst)
  1598. {
  1599.     dSP;
  1600.     SV *sv = TOPs;
  1601.     register char *s;
  1602.  
  1603.     if (!SvPADTMP(sv)) {
  1604.     dTARGET;
  1605.     sv_setsv(TARG, sv);
  1606.     sv = TARG;
  1607.     SETs(sv);
  1608.     }
  1609.     s = SvPV_force(sv, na);
  1610.     if (isLOWER(*s))
  1611.     *s = toUPPER(*s);
  1612.  
  1613.     RETURN;
  1614. }
  1615.  
  1616. PP(pp_lcfirst)
  1617. {
  1618.     dSP;
  1619.     SV *sv = TOPs;
  1620.     register char *s;
  1621.  
  1622.     if (!SvPADTMP(sv)) {
  1623.     dTARGET;
  1624.     sv_setsv(TARG, sv);
  1625.     sv = TARG;
  1626.     SETs(sv);
  1627.     }
  1628.     s = SvPV_force(sv, na);
  1629.     if (isUPPER(*s))
  1630.     *s = toLOWER(*s);
  1631.  
  1632.     SETs(sv);
  1633.     RETURN;
  1634. }
  1635.  
  1636. PP(pp_uc)
  1637. {
  1638.     dSP;
  1639.     SV *sv = TOPs;
  1640.     register char *s;
  1641.     register char *send;
  1642.     STRLEN len;
  1643.  
  1644.     if (!SvPADTMP(sv)) {
  1645.     dTARGET;
  1646.     sv_setsv(TARG, sv);
  1647.     sv = TARG;
  1648.     SETs(sv);
  1649.     }
  1650.     s = SvPV_force(sv, len);
  1651.     send = s + len;
  1652.     while (s < send) {
  1653.     if (isLOWER(*s))
  1654.         *s = toUPPER(*s);
  1655.     s++;
  1656.     }
  1657.     RETURN;
  1658. }
  1659.  
  1660. PP(pp_lc)
  1661. {
  1662.     dSP;
  1663.     SV *sv = TOPs;
  1664.     register char *s;
  1665.     register char *send;
  1666.     STRLEN len;
  1667.  
  1668.     if (!SvPADTMP(sv)) {
  1669.     dTARGET;
  1670.     sv_setsv(TARG, sv);
  1671.     sv = TARG;
  1672.     SETs(sv);
  1673.     }
  1674.     s = SvPV_force(sv, len);
  1675.     send = s + len;
  1676.     while (s < send) {
  1677.     if (isUPPER(*s))
  1678.         *s = toLOWER(*s);
  1679.     s++;
  1680.     }
  1681.     RETURN;
  1682. }
  1683.  
  1684. PP(pp_quotemeta)
  1685. {
  1686.     dSP; dTARGET;
  1687.     SV *sv = TOPs;
  1688.     STRLEN len;
  1689.     register char *s = SvPV(sv,len);
  1690.     register char *d;
  1691.  
  1692.     if (len) {
  1693.     (void)SvUPGRADE(TARG, SVt_PV);
  1694.     SvGROW(TARG, len * 2);
  1695.     d = SvPVX(TARG);
  1696.     while (len--) {
  1697.         if (!isALNUM(*s))
  1698.         *d++ = '\\';
  1699.         *d++ = *s++;
  1700.     }
  1701.     *d = '\0';
  1702.     SvCUR_set(TARG, d - SvPVX(TARG));
  1703.     (void)SvPOK_only(TARG);
  1704.     }
  1705.     else
  1706.     sv_setpvn(TARG, s, len);
  1707.     SETs(TARG);
  1708.     RETURN;
  1709. }
  1710.  
  1711. /* Arrays. */
  1712.  
  1713. PP(pp_aslice)
  1714. {
  1715.     dSP; dMARK; dORIGMARK;
  1716.     register SV** svp;
  1717.     register AV* av = (AV*)POPs;
  1718.     register I32 lval = op->op_flags & OPf_MOD;
  1719.     I32 arybase = curcop->cop_arybase;
  1720.     I32 elem;
  1721.  
  1722.     if (SvTYPE(av) == SVt_PVAV) {
  1723.     if (lval && op->op_private & OPpLVAL_INTRO) {
  1724.         I32 max = -1;
  1725.         for (svp = mark + 1; svp <= sp; svp++) {
  1726.         elem = SvIVx(*svp);
  1727.         if (elem > max)
  1728.             max = elem;
  1729.         }
  1730.         if (max > AvMAX(av))
  1731.         av_extend(av, max);
  1732.     }
  1733.     while (++MARK <= SP) {
  1734.         elem = SvIVx(*MARK);
  1735.  
  1736.         if (elem > 0)
  1737.         elem -= arybase;
  1738.         svp = av_fetch(av, elem, lval);
  1739.         if (lval) {
  1740.         if (!svp || *svp == &sv_undef)
  1741.             DIE(no_aelem, elem);
  1742.         if (op->op_private & OPpLVAL_INTRO)
  1743.             save_svref(svp);
  1744.         }
  1745.         *MARK = svp ? *svp : &sv_undef;
  1746.     }
  1747.     }
  1748.     if (GIMME != G_ARRAY) {
  1749.     MARK = ORIGMARK;
  1750.     *++MARK = *SP;
  1751.     SP = MARK;
  1752.     }
  1753.     RETURN;
  1754. }
  1755.  
  1756. /* Associative arrays. */
  1757.  
  1758. PP(pp_each)
  1759. {
  1760.     dSP; dTARGET;
  1761.     HV *hash = (HV*)POPs;
  1762.     HE *entry = hv_iternext(hash);
  1763.     I32 i;
  1764.     char *tmps;
  1765.  
  1766.     EXTEND(SP, 2);
  1767.     if (entry) {
  1768.     tmps = hv_iterkey(entry, &i);
  1769.     if (!i)
  1770.         tmps = "";
  1771.     PUSHs(sv_2mortal(newSVpv(tmps, i)));
  1772.     if (GIMME == G_ARRAY) {
  1773.         sv_setsv(TARG, hv_iterval(hash, entry));
  1774.         PUSHs(TARG);
  1775.     }
  1776.     }
  1777.     else if (GIMME == G_SCALAR)
  1778.     RETPUSHUNDEF;
  1779.  
  1780.     RETURN;
  1781. }
  1782.  
  1783. PP(pp_values)
  1784. {
  1785.     return do_kv(ARGS);
  1786. }
  1787.  
  1788. PP(pp_keys)
  1789. {
  1790.     return do_kv(ARGS);
  1791. }
  1792.  
  1793. PP(pp_delete)
  1794. {
  1795.     dSP;
  1796.     SV *sv;
  1797.     SV *tmpsv = POPs;
  1798.     HV *hv = (HV*)POPs;
  1799.     char *tmps;
  1800.     STRLEN len;
  1801.     if (SvTYPE(hv) != SVt_PVHV) {
  1802.     DIE("Not a HASH reference");
  1803.     }
  1804.     tmps = SvPV(tmpsv, len);
  1805.     sv = hv_delete(hv, tmps, len,
  1806.     op->op_private & OPpLEAVE_VOID ? G_DISCARD : 0);
  1807.     if (!sv)
  1808.     RETPUSHUNDEF;
  1809.     PUSHs(sv);
  1810.     RETURN;
  1811. }
  1812.  
  1813. PP(pp_exists)
  1814. {
  1815.     dSP;
  1816.     SV *tmpsv = POPs;
  1817.     HV *hv = (HV*)POPs;
  1818.     char *tmps;
  1819.     STRLEN len;
  1820.     if (SvTYPE(hv) != SVt_PVHV) {
  1821.     DIE("Not a HASH reference");
  1822.     }
  1823.     tmps = SvPV(tmpsv, len);
  1824.     if (hv_exists(hv, tmps, len))
  1825.     RETPUSHYES;
  1826.     RETPUSHNO;
  1827. }
  1828.  
  1829. PP(pp_hslice)
  1830. {
  1831.     dSP; dMARK; dORIGMARK;
  1832.     register SV **svp;
  1833.     register HV *hv = (HV*)POPs;
  1834.     register I32 lval = op->op_flags & OPf_MOD;
  1835.  
  1836.     if (SvTYPE(hv) == SVt_PVHV) {
  1837.     while (++MARK <= SP) {
  1838.         STRLEN keylen;
  1839.         char *key = SvPV(*MARK, keylen);
  1840.  
  1841.         svp = hv_fetch(hv, key, keylen, lval);
  1842.         if (lval) {
  1843.         if (!svp || *svp == &sv_undef)
  1844.             DIE(no_helem, key);
  1845.         if (op->op_private & OPpLVAL_INTRO)
  1846.             save_svref(svp);
  1847.         }
  1848.         *MARK = svp ? *svp : &sv_undef;
  1849.     }
  1850.     }
  1851.     if (GIMME != G_ARRAY) {
  1852.     MARK = ORIGMARK;
  1853.     *++MARK = *SP;
  1854.     SP = MARK;
  1855.     }
  1856.     RETURN;
  1857. }
  1858.  
  1859. /* List operators. */
  1860.  
  1861. PP(pp_list)
  1862. {
  1863.     dSP; dMARK;
  1864.     if (GIMME != G_ARRAY) {
  1865.     if (++MARK <= SP)
  1866.         *MARK = *SP;        /* unwanted list, return last item */
  1867.     else
  1868.         *MARK = &sv_undef;
  1869.     SP = MARK;
  1870.     }
  1871.     RETURN;
  1872. }
  1873.  
  1874. PP(pp_lslice)
  1875. {
  1876.     dSP;
  1877.     SV **lastrelem = stack_sp;
  1878.     SV **lastlelem = stack_base + POPMARK;
  1879.     SV **firstlelem = stack_base + POPMARK + 1;
  1880.     register SV **firstrelem = lastlelem + 1;
  1881.     I32 arybase = curcop->cop_arybase;
  1882.  
  1883.     register I32 max = lastrelem - lastlelem;
  1884.     register SV **lelem;
  1885.     register I32 ix;
  1886.  
  1887.     if (GIMME != G_ARRAY) {
  1888.     ix = SvIVx(*lastlelem);
  1889.     if (ix < 0)
  1890.         ix += max;
  1891.     else
  1892.         ix -= arybase;
  1893.     if (ix < 0 || ix >= max)
  1894.         *firstlelem = &sv_undef;
  1895.     else
  1896.         *firstlelem = firstrelem[ix];
  1897.     SP = firstlelem;
  1898.     RETURN;
  1899.     }
  1900.  
  1901.     if (max == 0) {
  1902.     SP = firstlelem - 1;
  1903.     RETURN;
  1904.     }
  1905.  
  1906.     for (lelem = firstlelem; lelem <= lastlelem; lelem++) {
  1907.     ix = SvIVx(*lelem);
  1908.     if (ix < 0) {
  1909.         ix += max;
  1910.         if (ix < 0)
  1911.         *lelem = &sv_undef;
  1912.         else if (!(*lelem = firstrelem[ix]))
  1913.         *lelem = &sv_undef;
  1914.     }
  1915.     else {
  1916.         ix -= arybase;
  1917.         if (ix >= max || !(*lelem = firstrelem[ix]))
  1918.         *lelem = &sv_undef;
  1919.     }
  1920.     }
  1921.     SP = lastlelem;
  1922.     RETURN;
  1923. }
  1924.  
  1925. PP(pp_anonlist)
  1926. {
  1927.     dSP; dMARK;
  1928.     I32 items = SP - MARK;
  1929.     SP = MARK;
  1930.     XPUSHs((SV*)sv_2mortal((SV*)av_make(items, MARK+1)));
  1931.     RETURN;
  1932. }
  1933.  
  1934. PP(pp_anonhash)
  1935. {
  1936.     dSP; dMARK; dORIGMARK;
  1937.     STRLEN len;
  1938.     HV* hv = (HV*)sv_2mortal((SV*)newHV());
  1939.  
  1940.     while (MARK < SP) {
  1941.     SV* key = *++MARK;
  1942.     char *tmps;
  1943.     SV *val = NEWSV(46, 0);
  1944.     if (MARK < SP)
  1945.         sv_setsv(val, *++MARK);
  1946.     else
  1947.         warn("Odd number of elements in hash list");
  1948.     tmps = SvPV(key,len);
  1949.     (void)hv_store(hv,tmps,len,val,0);
  1950.     }
  1951.     SP = ORIGMARK;
  1952.     XPUSHs((SV*)hv);
  1953.     RETURN;
  1954. }
  1955.  
  1956. PP(pp_splice)
  1957. {
  1958.     dSP; dMARK; dORIGMARK;
  1959.     register AV *ary = (AV*)*++MARK;
  1960.     register SV **src;
  1961.     register SV **dst;
  1962.     register I32 i;
  1963.     register I32 offset;
  1964.     register I32 length;
  1965.     I32 newlen;
  1966.     I32 after;
  1967.     I32 diff;
  1968.     SV **tmparyval = 0;
  1969.  
  1970.     SP++;
  1971.  
  1972.     if (++MARK < SP) {
  1973.     offset = SvIVx(*MARK);
  1974.     if (offset < 0)
  1975.         offset += AvFILL(ary) + 1;
  1976.     else
  1977.         offset -= curcop->cop_arybase;
  1978.     if (++MARK < SP) {
  1979.         length = SvIVx(*MARK++);
  1980.         if (length < 0)
  1981.         length = 0;
  1982.     }
  1983.     else
  1984.         length = AvMAX(ary) + 1;        /* close enough to infinity */
  1985.     }
  1986.     else {
  1987.     offset = 0;
  1988.     length = AvMAX(ary) + 1;
  1989.     }
  1990.     if (offset < 0) {
  1991.     length += offset;
  1992.     offset = 0;
  1993.     if (length < 0)
  1994.         length = 0;
  1995.     }
  1996.     if (offset > AvFILL(ary) + 1)
  1997.     offset = AvFILL(ary) + 1;
  1998.     after = AvFILL(ary) + 1 - (offset + length);
  1999.     if (after < 0) {                /* not that much array */
  2000.     length += after;            /* offset+length now in array */
  2001.     after = 0;
  2002.     if (!AvALLOC(ary))
  2003.         av_extend(ary, 0);
  2004.     }
  2005.  
  2006.     /* At this point, MARK .. SP-1 is our new LIST */
  2007.  
  2008.     newlen = SP - MARK;
  2009.     diff = newlen - length;
  2010.  
  2011.     if (diff < 0) {                /* shrinking the area */
  2012.     if (newlen) {
  2013.         New(451, tmparyval, newlen, SV*);    /* so remember insertion */
  2014.         Copy(MARK, tmparyval, newlen, SV*);
  2015.     }
  2016.  
  2017.     MARK = ORIGMARK + 1;
  2018.     if (GIMME == G_ARRAY) {            /* copy return vals to stack */
  2019.         MEXTEND(MARK, length);
  2020.         Copy(AvARRAY(ary)+offset, MARK, length, SV*);
  2021.         if (AvREAL(ary)) {
  2022.         for (i = length, dst = MARK; i; i--)
  2023.             sv_2mortal(*dst++);    /* free them eventualy */
  2024.         }
  2025.         MARK += length - 1;
  2026.     }
  2027.     else {
  2028.         *MARK = AvARRAY(ary)[offset+length-1];
  2029.         if (AvREAL(ary)) {
  2030.         sv_2mortal(*MARK);
  2031.         for (i = length - 1, dst = &AvARRAY(ary)[offset]; i > 0; i--)
  2032.             SvREFCNT_dec(*dst++);    /* free them now */
  2033.         }
  2034.     }
  2035.     AvFILL(ary) += diff;
  2036.  
  2037.     /* pull up or down? */
  2038.  
  2039.     if (offset < after) {            /* easier to pull up */
  2040.         if (offset) {            /* esp. if nothing to pull */
  2041.         src = &AvARRAY(ary)[offset-1];
  2042.         dst = src - diff;        /* diff is negative */
  2043.         for (i = offset; i > 0; i--)    /* can't trust Copy */
  2044.             *dst-- = *src--;
  2045.         }
  2046.         dst = AvARRAY(ary);
  2047.         SvPVX(ary) = (char*)(AvARRAY(ary) - diff); /* diff is negative */
  2048.         AvMAX(ary) += diff;
  2049.     }
  2050.     else {
  2051.         if (after) {            /* anything to pull down? */
  2052.         src = AvARRAY(ary) + offset + length;
  2053.         dst = src + diff;        /* diff is negative */
  2054.         Move(src, dst, after, SV*);
  2055.         }
  2056.         dst = &AvARRAY(ary)[AvFILL(ary)+1];
  2057.                         /* avoid later double free */
  2058.     }
  2059.     i = -diff;
  2060.     while (i)
  2061.         dst[--i] = &sv_undef;
  2062.     
  2063.     if (newlen) {
  2064.         for (src = tmparyval, dst = AvARRAY(ary) + offset;
  2065.           newlen; newlen--) {
  2066.         *dst = NEWSV(46, 0);
  2067.         sv_setsv(*dst++, *src++);
  2068.         }
  2069.         Safefree(tmparyval);
  2070.     }
  2071.     }
  2072.     else {                    /* no, expanding (or same) */
  2073.     if (length) {
  2074.         New(452, tmparyval, length, SV*);    /* so remember deletion */
  2075.         Copy(AvARRAY(ary)+offset, tmparyval, length, SV*);
  2076.     }
  2077.  
  2078.     if (diff > 0) {                /* expanding */
  2079.  
  2080.         /* push up or down? */
  2081.  
  2082.         if (offset < after && diff <= AvARRAY(ary) - AvALLOC(ary)) {
  2083.         if (offset) {
  2084.             src = AvARRAY(ary);
  2085.             dst = src - diff;
  2086.             Move(src, dst, offset, SV*);
  2087.         }
  2088.         SvPVX(ary) = (char*)(AvARRAY(ary) - diff);/* diff is positive */
  2089.         AvMAX(ary) += diff;
  2090.         AvFILL(ary) += diff;
  2091.         }
  2092.         else {
  2093.         if (AvFILL(ary) + diff >= AvMAX(ary))    /* oh, well */
  2094.             av_extend(ary, AvFILL(ary) + diff);
  2095.         AvFILL(ary) += diff;
  2096.  
  2097.         if (after) {
  2098.             dst = AvARRAY(ary) + AvFILL(ary);
  2099.             src = dst - diff;
  2100.             for (i = after; i; i--) {
  2101.             *dst-- = *src--;
  2102.             }
  2103.         }
  2104.         }
  2105.     }
  2106.  
  2107.     for (src = MARK, dst = AvARRAY(ary) + offset; newlen; newlen--) {
  2108.         *dst = NEWSV(46, 0);
  2109.         sv_setsv(*dst++, *src++);
  2110.     }
  2111.     MARK = ORIGMARK + 1;
  2112.     if (GIMME == G_ARRAY) {            /* copy return vals to stack */
  2113.         if (length) {
  2114.         Copy(tmparyval, MARK, length, SV*);
  2115.         if (AvREAL(ary)) {
  2116.             for (i = length, dst = MARK; i; i--)
  2117.             sv_2mortal(*dst++);    /* free them eventualy */
  2118.         }
  2119.         Safefree(tmparyval);
  2120.         }
  2121.         MARK += length - 1;
  2122.     }
  2123.     else if (length--) {
  2124.         *MARK = tmparyval[length];
  2125.         if (AvREAL(ary)) {
  2126.         sv_2mortal(*MARK);
  2127.         while (length-- > 0)
  2128.             SvREFCNT_dec(tmparyval[length]);
  2129.         }
  2130.         Safefree(tmparyval);
  2131.     }
  2132.     else
  2133.         *MARK = &sv_undef;
  2134.     }
  2135.     SP = MARK;
  2136.     RETURN;
  2137. }
  2138.  
  2139. PP(pp_push)
  2140. {
  2141.     dSP; dMARK; dORIGMARK; dTARGET;
  2142.     register AV *ary = (AV*)*++MARK;
  2143.     register SV *sv = &sv_undef;
  2144.  
  2145.     for (++MARK; MARK <= SP; MARK++) {
  2146.     sv = NEWSV(51, 0);
  2147.     if (*MARK)
  2148.         sv_setsv(sv, *MARK);
  2149.     av_push(ary, sv);
  2150.     }
  2151.     SP = ORIGMARK;
  2152.     PUSHi( AvFILL(ary) + 1 );
  2153.     RETURN;
  2154. }
  2155.  
  2156. PP(pp_pop)
  2157. {
  2158.     dSP;
  2159.     AV *av = (AV*)POPs;
  2160.     SV *sv = av_pop(av);
  2161.     if (sv != &sv_undef && AvREAL(av))
  2162.     (void)sv_2mortal(sv);
  2163.     PUSHs(sv);
  2164.     RETURN;
  2165. }
  2166.  
  2167. PP(pp_shift)
  2168. {
  2169.     dSP;
  2170.     AV *av = (AV*)POPs;
  2171.     SV *sv = av_shift(av);
  2172.     EXTEND(SP, 1);
  2173.     if (!sv)
  2174.     RETPUSHUNDEF;
  2175.     if (sv != &sv_undef && AvREAL(av))
  2176.     (void)sv_2mortal(sv);
  2177.     PUSHs(sv);
  2178.     RETURN;
  2179. }
  2180.  
  2181. PP(pp_unshift)
  2182. {
  2183.     dSP; dMARK; dORIGMARK; dTARGET;
  2184.     register AV *ary = (AV*)*++MARK;
  2185.     register SV *sv;
  2186.     register I32 i = 0;
  2187.  
  2188.     av_unshift(ary, SP - MARK);
  2189.     while (MARK < SP) {
  2190.     sv = NEWSV(27, 0);
  2191.     sv_setsv(sv, *++MARK);
  2192.     (void)av_store(ary, i++, sv);
  2193.     }
  2194.  
  2195.     SP = ORIGMARK;
  2196.     PUSHi( AvFILL(ary) + 1 );
  2197.     RETURN;
  2198. }
  2199.  
  2200. PP(pp_reverse)
  2201. {
  2202.     dSP; dMARK;
  2203.     register SV *tmp;
  2204.     SV **oldsp = SP;
  2205.  
  2206.     if (GIMME == G_ARRAY) {
  2207.     MARK++;
  2208.     while (MARK < SP) {
  2209.         tmp = *MARK;
  2210.         *MARK++ = *SP;
  2211.         *SP-- = tmp;
  2212.     }
  2213.     SP = oldsp;
  2214.     }
  2215.     else {
  2216.     register char *up;
  2217.     register char *down;
  2218.     register I32 tmp;
  2219.     dTARGET;
  2220.     STRLEN len;
  2221.  
  2222.     if (SP - MARK > 1)
  2223.         do_join(TARG, &sv_no, MARK, SP);
  2224.     else
  2225.         sv_setsv(TARG, *SP);
  2226.     up = SvPV_force(TARG, len);
  2227.     if (len > 1) {
  2228.         down = SvPVX(TARG) + len - 1;
  2229.         while (down > up) {
  2230.         tmp = *up;
  2231.         *up++ = *down;
  2232.         *down-- = tmp;
  2233.         }
  2234.         (void)SvPOK_only(TARG);
  2235.     }
  2236.     SP = MARK + 1;
  2237.     SETTARG;
  2238.     }
  2239.     RETURN;
  2240. }
  2241.  
  2242. /* Explosives and implosives. */
  2243.  
  2244. PP(pp_unpack)
  2245. {
  2246.     dSP;
  2247.     dPOPPOPssrl;
  2248.     SV *sv;
  2249.     STRLEN llen;
  2250.     STRLEN rlen;
  2251.     register char *pat = SvPV(left, llen);
  2252.     register char *s = SvPV(right, rlen);
  2253.     char *strend = s + rlen;
  2254.     char *strbeg = s;
  2255.     register char *patend = pat + llen;
  2256.     I32 datumtype;
  2257.     register I32 len;
  2258.     register I32 bits;
  2259.  
  2260.     /* These must not be in registers: */
  2261.     I16 ashort;
  2262.     int aint;
  2263.     I32 along;
  2264. #ifdef HAS_QUAD
  2265.     Quad_t aquad;
  2266. #endif
  2267.     U16 aushort;
  2268.     unsigned int auint;
  2269.     U32 aulong;
  2270. #ifdef HAS_QUAD
  2271.     unsigned Quad_t auquad;
  2272. #endif
  2273.     char *aptr;
  2274.     float afloat;
  2275.     double adouble;
  2276.     I32 checksum = 0;
  2277.     register U32 culong;
  2278.     double cdouble;
  2279.     static char* bitcount = 0;
  2280.  
  2281.     if (GIMME != G_ARRAY) {        /* arrange to do first one only */
  2282.     /*SUPPRESS 530*/
  2283.     for (patend = pat; !isALPHA(*patend) || *patend == 'x'; patend++) ;
  2284.     if (strchr("aAbBhHP", *patend) || *pat == '%') {
  2285.         patend++;
  2286.         while (isDIGIT(*patend) || *patend == '*')
  2287.         patend++;
  2288.     }
  2289.     else
  2290.         patend++;
  2291.     }
  2292.     while (pat < patend) {
  2293.       reparse:
  2294.     datumtype = *pat++;
  2295.     if (pat >= patend)
  2296.         len = 1;
  2297.     else if (*pat == '*') {
  2298.         len = strend - strbeg;    /* long enough */
  2299.         pat++;
  2300.     }
  2301.     else if (isDIGIT(*pat)) {
  2302.         len = *pat++ - '0';
  2303.         while (isDIGIT(*pat))
  2304.         len = (len * 10) + (*pat++ - '0');
  2305.     }
  2306.     else
  2307.         len = (datumtype != '@');
  2308.     switch(datumtype) {
  2309.     default:
  2310.         break;
  2311.     case '%':
  2312.         if (len == 1 && pat[-1] != '1')
  2313.         len = 16;
  2314.         checksum = len;
  2315.         culong = 0;
  2316.         cdouble = 0;
  2317.         if (pat < patend)
  2318.         goto reparse;
  2319.         break;
  2320.     case '@':
  2321.         if (len > strend - strbeg)
  2322.         DIE("@ outside of string");
  2323.         s = strbeg + len;
  2324.         break;
  2325.     case 'X':
  2326.         if (len > s - strbeg)
  2327.         DIE("X outside of string");
  2328.         s -= len;
  2329.         break;
  2330.     case 'x':
  2331.         if (len > strend - s)
  2332.         DIE("x outside of string");
  2333.         s += len;
  2334.         break;
  2335.     case 'A':
  2336.     case 'a':
  2337.         if (len > strend - s)
  2338.         len = strend - s;
  2339.         if (checksum)
  2340.         goto uchar_checksum;
  2341.         sv = NEWSV(35, len);
  2342.         sv_setpvn(sv, s, len);
  2343.         s += len;
  2344.         if (datumtype == 'A') {
  2345.         aptr = s;    /* borrow register */
  2346.         s = SvPVX(sv) + len - 1;
  2347.         while (s >= SvPVX(sv) && (!*s || isSPACE(*s)))
  2348.             s--;
  2349.         *++s = '\0';
  2350.         SvCUR_set(sv, s - SvPVX(sv));
  2351.         s = aptr;    /* unborrow register */
  2352.         }
  2353.         XPUSHs(sv_2mortal(sv));
  2354.         break;
  2355.     case 'B':
  2356.     case 'b':
  2357.         if (pat[-1] == '*' || len > (strend - s) * 8)
  2358.         len = (strend - s) * 8;
  2359.         if (checksum) {
  2360.         if (!bitcount) {
  2361.             Newz(601, bitcount, 256, char);
  2362.             for (bits = 1; bits < 256; bits++) {
  2363.             if (bits & 1)    bitcount[bits]++;
  2364.             if (bits & 2)    bitcount[bits]++;
  2365.             if (bits & 4)    bitcount[bits]++;
  2366.             if (bits & 8)    bitcount[bits]++;
  2367.             if (bits & 16)    bitcount[bits]++;
  2368.             if (bits & 32)    bitcount[bits]++;
  2369.             if (bits & 64)    bitcount[bits]++;
  2370.             if (bits & 128)    bitcount[bits]++;
  2371.             }
  2372.         }
  2373.         while (len >= 8) {
  2374.             culong += bitcount[*(unsigned char*)s++];
  2375.             len -= 8;
  2376.         }
  2377.         if (len) {
  2378.             bits = *s;
  2379.             if (datumtype == 'b') {
  2380.             while (len-- > 0) {
  2381.                 if (bits & 1) culong++;
  2382.                 bits >>= 1;
  2383.             }
  2384.             }
  2385.             else {
  2386.             while (len-- > 0) {
  2387.                 if (bits & 128) culong++;
  2388.                 bits <<= 1;
  2389.             }
  2390.             }
  2391.         }
  2392.         break;
  2393.         }
  2394.         sv = NEWSV(35, len + 1);
  2395.         SvCUR_set(sv, len);
  2396.         SvPOK_on(sv);
  2397.         aptr = pat;            /* borrow register */
  2398.         pat = SvPVX(sv);
  2399.         if (datumtype == 'b') {
  2400.         aint = len;
  2401.         for (len = 0; len < aint; len++) {
  2402.             if (len & 7)        /*SUPPRESS 595*/
  2403.             bits >>= 1;
  2404.             else
  2405.             bits = *s++;
  2406.             *pat++ = '0' + (bits & 1);
  2407.         }
  2408.         }
  2409.         else {
  2410.         aint = len;
  2411.         for (len = 0; len < aint; len++) {
  2412.             if (len & 7)
  2413.             bits <<= 1;
  2414.             else
  2415.             bits = *s++;
  2416.             *pat++ = '0' + ((bits & 128) != 0);
  2417.         }
  2418.         }
  2419.         *pat = '\0';
  2420.         pat = aptr;            /* unborrow register */
  2421.         XPUSHs(sv_2mortal(sv));
  2422.         break;
  2423.     case 'H':
  2424.     case 'h':
  2425.         if (pat[-1] == '*' || len > (strend - s) * 2)
  2426.         len = (strend - s) * 2;
  2427.         sv = NEWSV(35, len + 1);
  2428.         SvCUR_set(sv, len);
  2429.         SvPOK_on(sv);
  2430.         aptr = pat;            /* borrow register */
  2431.         pat = SvPVX(sv);
  2432.         if (datumtype == 'h') {
  2433.         aint = len;
  2434.         for (len = 0; len < aint; len++) {
  2435.             if (len & 1)
  2436.             bits >>= 4;
  2437.             else
  2438.             bits = *s++;
  2439.             *pat++ = hexdigit[bits & 15];
  2440.         }
  2441.         }
  2442.         else {
  2443.         aint = len;
  2444.         for (len = 0; len < aint; len++) {
  2445.             if (len & 1)
  2446.             bits <<= 4;
  2447.             else
  2448.             bits = *s++;
  2449.             *pat++ = hexdigit[(bits >> 4) & 15];
  2450.         }
  2451.         }
  2452.         *pat = '\0';
  2453.         pat = aptr;            /* unborrow register */
  2454.         XPUSHs(sv_2mortal(sv));
  2455.         break;
  2456.     case 'c':
  2457.         if (len > strend - s)
  2458.         len = strend - s;
  2459.         if (checksum) {
  2460.         while (len-- > 0) {
  2461.             aint = *s++;
  2462.             if (aint >= 128)    /* fake up signed chars */
  2463.             aint -= 256;
  2464.             culong += aint;
  2465.         }
  2466.         }
  2467.         else {
  2468.         EXTEND(SP, len);
  2469.         while (len-- > 0) {
  2470.             aint = *s++;
  2471.             if (aint >= 128)    /* fake up signed chars */
  2472.             aint -= 256;
  2473.             sv = NEWSV(36, 0);
  2474.             sv_setiv(sv, (I32)aint);
  2475.             PUSHs(sv_2mortal(sv));
  2476.         }
  2477.         }
  2478.         break;
  2479.     case 'C':
  2480.         if (len > strend - s)
  2481.         len = strend - s;
  2482.         if (checksum) {
  2483.           uchar_checksum:
  2484.         while (len-- > 0) {
  2485.             auint = *s++ & 255;
  2486.             culong += auint;
  2487.         }
  2488.         }
  2489.         else {
  2490.         EXTEND(SP, len);
  2491.         while (len-- > 0) {
  2492.             auint = *s++ & 255;
  2493.             sv = NEWSV(37, 0);
  2494.             sv_setiv(sv, (I32)auint);
  2495.             PUSHs(sv_2mortal(sv));
  2496.         }
  2497.         }
  2498.         break;
  2499.     case 's':
  2500.         along = (strend - s) / sizeof(I16);
  2501.         if (len > along)
  2502.         len = along;
  2503.         if (checksum) {
  2504.         while (len-- > 0) {
  2505.             Copy(s, &ashort, 1, I16);
  2506.             s += sizeof(I16);
  2507.             culong += ashort;
  2508.         }
  2509.         }
  2510.         else {
  2511.         EXTEND(SP, len);
  2512.         while (len-- > 0) {
  2513.             Copy(s, &ashort, 1, I16);
  2514.             s += sizeof(I16);
  2515.             sv = NEWSV(38, 0);
  2516.             sv_setiv(sv, (I32)ashort);
  2517.             PUSHs(sv_2mortal(sv));
  2518.         }
  2519.         }
  2520.         break;
  2521.     case 'v':
  2522.     case 'n':
  2523.     case 'S':
  2524.         along = (strend - s) / sizeof(U16);
  2525.         if (len > along)
  2526.         len = along;
  2527.         if (checksum) {
  2528.         while (len-- > 0) {
  2529.             Copy(s, &aushort, 1, U16);
  2530.             s += sizeof(U16);
  2531. #ifdef HAS_NTOHS
  2532.             if (datumtype == 'n')
  2533.             aushort = ntohs(aushort);
  2534. #endif
  2535. #ifdef HAS_VTOHS
  2536.             if (datumtype == 'v')
  2537.             aushort = vtohs(aushort);
  2538. #endif
  2539.             culong += aushort;
  2540.         }
  2541.         }
  2542.         else {
  2543.         EXTEND(SP, len);
  2544.         while (len-- > 0) {
  2545.             Copy(s, &aushort, 1, U16);
  2546.             s += sizeof(U16);
  2547.             sv = NEWSV(39, 0);
  2548. #ifdef HAS_NTOHS
  2549.             if (datumtype == 'n')
  2550.             aushort = ntohs(aushort);
  2551. #endif
  2552. #ifdef HAS_VTOHS
  2553.             if (datumtype == 'v')
  2554.             aushort = vtohs(aushort);
  2555. #endif
  2556.             sv_setiv(sv, (I32)aushort);
  2557.             PUSHs(sv_2mortal(sv));
  2558.         }
  2559.         }
  2560.         break;
  2561.     case 'i':
  2562.         along = (strend - s) / sizeof(int);
  2563.         if (len > along)
  2564.         len = along;
  2565.         if (checksum) {
  2566.         while (len-- > 0) {
  2567.             Copy(s, &aint, 1, int);
  2568.             s += sizeof(int);
  2569.             if (checksum > 32)
  2570.             cdouble += (double)aint;
  2571.             else
  2572.             culong += aint;
  2573.         }
  2574.         }
  2575.         else {
  2576.         EXTEND(SP, len);
  2577.         while (len-- > 0) {
  2578.             Copy(s, &aint, 1, int);
  2579.             s += sizeof(int);
  2580.             sv = NEWSV(40, 0);
  2581.             sv_setiv(sv, (I32)aint);
  2582.             PUSHs(sv_2mortal(sv));
  2583.         }
  2584.         }
  2585.         break;
  2586.     case 'I':
  2587.         along = (strend - s) / sizeof(unsigned int);
  2588.         if (len > along)
  2589.         len = along;
  2590.         if (checksum) {
  2591.         while (len-- > 0) {
  2592.             Copy(s, &auint, 1, unsigned int);
  2593.             s += sizeof(unsigned int);
  2594.             if (checksum > 32)
  2595.             cdouble += (double)auint;
  2596.             else
  2597.             culong += auint;
  2598.         }
  2599.         }
  2600.         else {
  2601.         EXTEND(SP, len);
  2602.         while (len-- > 0) {
  2603.             Copy(s, &auint, 1, unsigned int);
  2604.             s += sizeof(unsigned int);
  2605.             sv = NEWSV(41, 0);
  2606.             sv_setiv(sv, (I32)auint);
  2607.             PUSHs(sv_2mortal(sv));
  2608.         }
  2609.         }
  2610.         break;
  2611.     case 'l':
  2612.         along = (strend - s) / sizeof(I32);
  2613.         if (len > along)
  2614.         len = along;
  2615.         if (checksum) {
  2616.         while (len-- > 0) {
  2617.             Copy(s, &along, 1, I32);
  2618.             s += sizeof(I32);
  2619.             if (checksum > 32)
  2620.             cdouble += (double)along;
  2621.             else
  2622.             culong += along;
  2623.         }
  2624.         }
  2625.         else {
  2626.         EXTEND(SP, len);
  2627.         while (len-- > 0) {
  2628.             Copy(s, &along, 1, I32);
  2629.             s += sizeof(I32);
  2630.             sv = NEWSV(42, 0);
  2631.             sv_setiv(sv, (I32)along);
  2632.             PUSHs(sv_2mortal(sv));
  2633.         }
  2634.         }
  2635.         break;
  2636.     case 'V':
  2637.     case 'N':
  2638.     case 'L':
  2639.         along = (strend - s) / sizeof(U32);
  2640.         if (len > along)
  2641.         len = along;
  2642.         if (checksum) {
  2643.         while (len-- > 0) {
  2644.             Copy(s, &aulong, 1, U32);
  2645.             s += sizeof(U32);
  2646. #ifdef HAS_NTOHL
  2647.             if (datumtype == 'N')
  2648.             aulong = ntohl(aulong);
  2649. #endif
  2650. #ifdef HAS_VTOHL
  2651.             if (datumtype == 'V')
  2652.             aulong = vtohl(aulong);
  2653. #endif
  2654.             if (checksum > 32)
  2655.             cdouble += (double)aulong;
  2656.             else
  2657.             culong += aulong;
  2658.         }
  2659.         }
  2660.         else {
  2661.         EXTEND(SP, len);
  2662.         while (len-- > 0) {
  2663.             Copy(s, &aulong, 1, U32);
  2664.             s += sizeof(U32);
  2665.             sv = NEWSV(43, 0);
  2666. #ifdef HAS_NTOHL
  2667.             if (datumtype == 'N')
  2668.             aulong = ntohl(aulong);
  2669. #endif
  2670. #ifdef HAS_VTOHL
  2671.             if (datumtype == 'V')
  2672.             aulong = vtohl(aulong);
  2673. #endif
  2674.             sv_setnv(sv, (double)aulong);
  2675.             PUSHs(sv_2mortal(sv));
  2676.         }
  2677.         }
  2678.         break;
  2679.     case 'p':
  2680.         along = (strend - s) / sizeof(char*);
  2681.         if (len > along)
  2682.         len = along;
  2683.         EXTEND(SP, len);
  2684.         while (len-- > 0) {
  2685.         if (sizeof(char*) > strend - s)
  2686.             break;
  2687.         else {
  2688.             Copy(s, &aptr, 1, char*);
  2689.             s += sizeof(char*);
  2690.         }
  2691.         sv = NEWSV(44, 0);
  2692.         if (aptr)
  2693.             sv_setpv(sv, aptr);
  2694.         PUSHs(sv_2mortal(sv));
  2695.         }
  2696.         break;
  2697.     case 'P':
  2698.         EXTEND(SP, 1);
  2699.         if (sizeof(char*) > strend - s)
  2700.         break;
  2701.         else {
  2702.         Copy(s, &aptr, 1, char*);
  2703.         s += sizeof(char*);
  2704.         }
  2705.         sv = NEWSV(44, 0);
  2706.         if (aptr)
  2707.         sv_setpvn(sv, aptr, len);
  2708.         PUSHs(sv_2mortal(sv));
  2709.         break;
  2710. #ifdef HAS_QUAD
  2711.     case 'q':
  2712.         EXTEND(SP, len);
  2713.         while (len-- > 0) {
  2714.         if (s + sizeof(Quad_t) > strend)
  2715.             aquad = 0;
  2716.         else {
  2717.             Copy(s, &aquad, 1, Quad_t);
  2718.             s += sizeof(Quad_t);
  2719.         }
  2720.         sv = NEWSV(42, 0);
  2721.         sv_setiv(sv, (IV)aquad);
  2722.         PUSHs(sv_2mortal(sv));
  2723.         }
  2724.         break;
  2725.     case 'Q':
  2726.         EXTEND(SP, len);
  2727.         while (len-- > 0) {
  2728.         if (s + sizeof(unsigned Quad_t) > strend)
  2729.             auquad = 0;
  2730.         else {
  2731.             Copy(s, &auquad, 1, unsigned Quad_t);
  2732.             s += sizeof(unsigned Quad_t);
  2733.         }
  2734.         sv = NEWSV(43, 0);
  2735.         sv_setiv(sv, (IV)auquad);
  2736.         PUSHs(sv_2mortal(sv));
  2737.         }
  2738.         break;
  2739. #endif
  2740.     /* float and double added gnb@melba.bby.oz.au 22/11/89 */
  2741.     case 'f':
  2742.     case 'F':
  2743.         along = (strend - s) / sizeof(float);
  2744.         if (len > along)
  2745.         len = along;
  2746.         if (checksum) {
  2747.         while (len-- > 0) {
  2748.             Copy(s, &afloat, 1, float);
  2749.             s += sizeof(float);
  2750.             cdouble += afloat;
  2751.         }
  2752.         }
  2753.         else {
  2754.         EXTEND(SP, len);
  2755.         while (len-- > 0) {
  2756.             Copy(s, &afloat, 1, float);
  2757.             s += sizeof(float);
  2758.             sv = NEWSV(47, 0);
  2759.             sv_setnv(sv, (double)afloat);
  2760.             PUSHs(sv_2mortal(sv));
  2761.         }
  2762.         }
  2763.         break;
  2764.     case 'd':
  2765.     case 'D':
  2766.         along = (strend - s) / sizeof(double);
  2767.         if (len > along)
  2768.         len = along;
  2769.         if (checksum) {
  2770.         while (len-- > 0) {
  2771.             Copy(s, &adouble, 1, double);
  2772.             s += sizeof(double);
  2773.             cdouble += adouble;
  2774.         }
  2775.         }
  2776.         else {
  2777.         EXTEND(SP, len);
  2778.         while (len-- > 0) {
  2779.             Copy(s, &adouble, 1, double);
  2780.             s += sizeof(double);
  2781.             sv = NEWSV(48, 0);
  2782.             sv_setnv(sv, (double)adouble);
  2783.             PUSHs(sv_2mortal(sv));
  2784.         }
  2785.         }
  2786.         break;
  2787.     case 'u':
  2788.         along = (strend - s) * 3 / 4;
  2789.         sv = NEWSV(42, along);
  2790.         while (s < strend && *s > ' ' && *s < 'a') {
  2791.         I32 a, b, c, d;
  2792.         char hunk[4];
  2793.  
  2794.         hunk[3] = '\0';
  2795.         len = (*s++ - ' ') & 077;
  2796.         while (len > 0) {
  2797.             if (s < strend && *s >= ' ')
  2798.             a = (*s++ - ' ') & 077;
  2799.             else
  2800.             a = 0;
  2801.             if (s < strend && *s >= ' ')
  2802.             b = (*s++ - ' ') & 077;
  2803.             else
  2804.             b = 0;
  2805.             if (s < strend && *s >= ' ')
  2806.             c = (*s++ - ' ') & 077;
  2807.             else
  2808.             c = 0;
  2809.             if (s < strend && *s >= ' ')
  2810.             d = (*s++ - ' ') & 077;
  2811.             else
  2812.             d = 0;
  2813.             hunk[0] = a << 2 | b >> 4;
  2814.             hunk[1] = b << 4 | c >> 2;
  2815.             hunk[2] = c << 6 | d;
  2816.             sv_catpvn(sv, hunk, len > 3 ? 3 : len);
  2817.             len -= 3;
  2818.         }
  2819.         if (*s == '\n')
  2820.             s++;
  2821.         else if (s[1] == '\n')        /* possible checksum byte */
  2822.             s += 2;
  2823.         }
  2824.         XPUSHs(sv_2mortal(sv));
  2825.         break;
  2826.     }
  2827.     if (checksum) {
  2828.         sv = NEWSV(42, 0);
  2829.         if (strchr("fFdD", datumtype) ||
  2830.           (checksum > 32 && strchr("iIlLN", datumtype)) ) {
  2831.         double trouble;
  2832.  
  2833.         adouble = 1.0;
  2834.         while (checksum >= 16) {
  2835.             checksum -= 16;
  2836.             adouble *= 65536.0;
  2837.         }
  2838.         while (checksum >= 4) {
  2839.             checksum -= 4;
  2840.             adouble *= 16.0;
  2841.         }
  2842.         while (checksum--)
  2843.             adouble *= 2.0;
  2844.         along = (1 << checksum) - 1;
  2845.         while (cdouble < 0.0)
  2846.             cdouble += adouble;
  2847.         cdouble = modf(cdouble / adouble, &trouble) * adouble;
  2848.         sv_setnv(sv, cdouble);
  2849.         }
  2850.         else {
  2851.         if (checksum < 32) {
  2852.             along = (1 << checksum) - 1;
  2853.             culong &= (U32)along;
  2854.         }
  2855.         sv_setnv(sv, (double)culong);
  2856.         }
  2857.         XPUSHs(sv_2mortal(sv));
  2858.         checksum = 0;
  2859.     }
  2860.     }
  2861.     RETURN;
  2862. }
  2863.  
  2864. static void
  2865. doencodes(sv, s, len)
  2866. register SV *sv;
  2867. register char *s;
  2868. register I32 len;
  2869. {
  2870.     char hunk[5];
  2871.  
  2872.     *hunk = len + ' ';
  2873.     sv_catpvn(sv, hunk, 1);
  2874.     hunk[4] = '\0';
  2875.     while (len > 0) {
  2876.     hunk[0] = ' ' + (077 & (*s >> 2));
  2877.     hunk[1] = ' ' + (077 & ((*s << 4) & 060 | (s[1] >> 4) & 017));
  2878.     hunk[2] = ' ' + (077 & ((s[1] << 2) & 074 | (s[2] >> 6) & 03));
  2879.     hunk[3] = ' ' + (077 & (s[2] & 077));
  2880.     sv_catpvn(sv, hunk, 4);
  2881.     s += 3;
  2882.     len -= 3;
  2883.     }
  2884.     for (s = SvPVX(sv); *s; s++) {
  2885.     if (*s == ' ')
  2886.         *s = '`';
  2887.     }
  2888.     sv_catpvn(sv, "\n", 1);
  2889. }
  2890.  
  2891. PP(pp_pack)
  2892. {
  2893.     dSP; dMARK; dORIGMARK; dTARGET;
  2894.     register SV *cat = TARG;
  2895.     register I32 items;
  2896.     STRLEN fromlen;
  2897.     register char *pat = SvPVx(*++MARK, fromlen);
  2898.     register char *patend = pat + fromlen;
  2899.     register I32 len;
  2900.     I32 datumtype;
  2901.     SV *fromstr;
  2902.     /*SUPPRESS 442*/
  2903.     static char null10[] = {0,0,0,0,0,0,0,0,0,0};
  2904.     static char *space10 = "          ";
  2905.  
  2906.     /* These must not be in registers: */
  2907.     char achar;
  2908.     I16 ashort;
  2909.     int aint;
  2910.     unsigned int auint;
  2911.     I32 along;
  2912.     U32 aulong;
  2913. #ifdef HAS_QUAD
  2914.     Quad_t aquad;
  2915.     unsigned Quad_t auquad;
  2916. #endif
  2917.     char *aptr;
  2918.     float afloat;
  2919.     double adouble;
  2920.  
  2921.     items = SP - MARK;
  2922.     MARK++;
  2923.     sv_setpvn(cat, "", 0);
  2924.     while (pat < patend) {
  2925. #define NEXTFROM (items-- > 0 ? *MARK++ : &sv_no)
  2926.     datumtype = *pat++;
  2927.     if (*pat == '*') {
  2928.         len = strchr("@Xxu", datumtype) ? 0 : items;
  2929.         pat++;
  2930.     }
  2931.     else if (isDIGIT(*pat)) {
  2932.         len = *pat++ - '0';
  2933.         while (isDIGIT(*pat))
  2934.         len = (len * 10) + (*pat++ - '0');
  2935.     }
  2936.     else
  2937.         len = 1;
  2938.     switch(datumtype) {
  2939.     default:
  2940.         break;
  2941.     case '%':
  2942.         DIE("%% may only be used in unpack");
  2943.     case '@':
  2944.         len -= SvCUR(cat);
  2945.         if (len > 0)
  2946.         goto grow;
  2947.         len = -len;
  2948.         if (len > 0)
  2949.         goto shrink;
  2950.         break;
  2951.     case 'X':
  2952.       shrink:
  2953.         if (SvCUR(cat) < len)
  2954.         DIE("X outside of string");
  2955.         SvCUR(cat) -= len;
  2956.         *SvEND(cat) = '\0';
  2957.         break;
  2958.     case 'x':
  2959.       grow:
  2960.         while (len >= 10) {
  2961.         sv_catpvn(cat, null10, 10);
  2962.         len -= 10;
  2963.         }
  2964.         sv_catpvn(cat, null10, len);
  2965.         break;
  2966.     case 'A':
  2967.     case 'a':
  2968.         fromstr = NEXTFROM;
  2969.         aptr = SvPV(fromstr, fromlen);
  2970.         if (pat[-1] == '*')
  2971.         len = fromlen;
  2972.         if (fromlen > len)
  2973.         sv_catpvn(cat, aptr, len);
  2974.         else {
  2975.         sv_catpvn(cat, aptr, fromlen);
  2976.         len -= fromlen;
  2977.         if (datumtype == 'A') {
  2978.             while (len >= 10) {
  2979.             sv_catpvn(cat, space10, 10);
  2980.             len -= 10;
  2981.             }
  2982.             sv_catpvn(cat, space10, len);
  2983.         }
  2984.         else {
  2985.             while (len >= 10) {
  2986.             sv_catpvn(cat, null10, 10);
  2987.             len -= 10;
  2988.             }
  2989.             sv_catpvn(cat, null10, len);
  2990.         }
  2991.         }
  2992.         break;
  2993.     case 'B':
  2994.     case 'b':
  2995.         {
  2996.         char *savepat = pat;
  2997.         I32 saveitems;
  2998.  
  2999.         fromstr = NEXTFROM;
  3000.         saveitems = items;
  3001.         aptr = SvPV(fromstr, fromlen);
  3002.         if (pat[-1] == '*')
  3003.             len = fromlen;
  3004.         pat = aptr;
  3005.         aint = SvCUR(cat);
  3006.         SvCUR(cat) += (len+7)/8;
  3007.         SvGROW(cat, SvCUR(cat) + 1);
  3008.         aptr = SvPVX(cat) + aint;
  3009.         if (len > fromlen)
  3010.             len = fromlen;
  3011.         aint = len;
  3012.         items = 0;
  3013.         if (datumtype == 'B') {
  3014.             for (len = 0; len++ < aint;) {
  3015.             items |= *pat++ & 1;
  3016.             if (len & 7)
  3017.                 items <<= 1;
  3018.             else {
  3019.                 *aptr++ = items & 0xff;
  3020.                 items = 0;
  3021.             }
  3022.             }
  3023.         }
  3024.         else {
  3025.             for (len = 0; len++ < aint;) {
  3026.             if (*pat++ & 1)
  3027.                 items |= 128;
  3028.             if (len & 7)
  3029.                 items >>= 1;
  3030.             else {
  3031.                 *aptr++ = items & 0xff;
  3032.                 items = 0;
  3033.             }
  3034.             }
  3035.         }
  3036.         if (aint & 7) {
  3037.             if (datumtype == 'B')
  3038.             items <<= 7 - (aint & 7);
  3039.             else
  3040.             items >>= 7 - (aint & 7);
  3041.             *aptr++ = items & 0xff;
  3042.         }
  3043.         pat = SvPVX(cat) + SvCUR(cat);
  3044.         while (aptr <= pat)
  3045.             *aptr++ = '\0';
  3046.  
  3047.         pat = savepat;
  3048.         items = saveitems;
  3049.         }
  3050.         break;
  3051.     case 'H':
  3052.     case 'h':
  3053.         {
  3054.         char *savepat = pat;
  3055.         I32 saveitems;
  3056.  
  3057.         fromstr = NEXTFROM;
  3058.         saveitems = items;
  3059.         aptr = SvPV(fromstr, fromlen);
  3060.         if (pat[-1] == '*')
  3061.             len = fromlen;
  3062.         pat = aptr;
  3063.         aint = SvCUR(cat);
  3064.         SvCUR(cat) += (len+1)/2;
  3065.         SvGROW(cat, SvCUR(cat) + 1);
  3066.         aptr = SvPVX(cat) + aint;
  3067.         if (len > fromlen)
  3068.             len = fromlen;
  3069.         aint = len;
  3070.         items = 0;
  3071.         if (datumtype == 'H') {
  3072.             for (len = 0; len++ < aint;) {
  3073.             if (isALPHA(*pat))
  3074.                 items |= ((*pat++ & 15) + 9) & 15;
  3075.             else
  3076.                 items |= *pat++ & 15;
  3077.             if (len & 1)
  3078.                 items <<= 4;
  3079.             else {
  3080.                 *aptr++ = items & 0xff;
  3081.                 items = 0;
  3082.             }
  3083.             }
  3084.         }
  3085.         else {
  3086.             for (len = 0; len++ < aint;) {
  3087.             if (isALPHA(*pat))
  3088.                 items |= (((*pat++ & 15) + 9) & 15) << 4;
  3089.             else
  3090.                 items |= (*pat++ & 15) << 4;
  3091.             if (len & 1)
  3092.                 items >>= 4;
  3093.             else {
  3094.                 *aptr++ = items & 0xff;
  3095.                 items = 0;
  3096.             }
  3097.             }
  3098.         }
  3099.         if (aint & 1)
  3100.             *aptr++ = items & 0xff;
  3101.         pat = SvPVX(cat) + SvCUR(cat);
  3102.         while (aptr <= pat)
  3103.             *aptr++ = '\0';
  3104.  
  3105.         pat = savepat;
  3106.         items = saveitems;
  3107.         }
  3108.         break;
  3109.     case 'C':
  3110.     case 'c':
  3111.         while (len-- > 0) {
  3112.         fromstr = NEXTFROM;
  3113.         aint = SvIV(fromstr);
  3114.         achar = aint;
  3115.         sv_catpvn(cat, &achar, sizeof(char));
  3116.         }
  3117.         break;
  3118.     /* Float and double added by gnb@melba.bby.oz.au  22/11/89 */
  3119.     case 'f':
  3120.     case 'F':
  3121.         while (len-- > 0) {
  3122.         fromstr = NEXTFROM;
  3123.         afloat = (float)SvNV(fromstr);
  3124.         sv_catpvn(cat, (char *)&afloat, sizeof (float));
  3125.         }
  3126.         break;
  3127.     case 'd':
  3128.     case 'D':
  3129.         while (len-- > 0) {
  3130.         fromstr = NEXTFROM;
  3131.         adouble = (double)SvNV(fromstr);
  3132.         sv_catpvn(cat, (char *)&adouble, sizeof (double));
  3133.         }
  3134.         break;
  3135.     case 'n':
  3136.         while (len-- > 0) {
  3137.         fromstr = NEXTFROM;
  3138.         ashort = (I16)SvIV(fromstr);
  3139. #ifdef HAS_HTONS
  3140.         ashort = htons(ashort);
  3141. #endif
  3142.         sv_catpvn(cat, (char*)&ashort, sizeof(I16));
  3143.         }
  3144.         break;
  3145.     case 'v':
  3146.         while (len-- > 0) {
  3147.         fromstr = NEXTFROM;
  3148.         ashort = (I16)SvIV(fromstr);
  3149. #ifdef HAS_HTOVS
  3150.         ashort = htovs(ashort);
  3151. #endif
  3152.         sv_catpvn(cat, (char*)&ashort, sizeof(I16));
  3153.         }
  3154.         break;
  3155.     case 'S':
  3156.     case 's':
  3157.         while (len-- > 0) {
  3158.         fromstr = NEXTFROM;
  3159.         ashort = (I16)SvIV(fromstr);
  3160.         sv_catpvn(cat, (char*)&ashort, sizeof(I16));
  3161.         }
  3162.         break;
  3163.     case 'I':
  3164.         while (len-- > 0) {
  3165.         fromstr = NEXTFROM;
  3166.         auint = U_I(SvNV(fromstr));
  3167.         sv_catpvn(cat, (char*)&auint, sizeof(unsigned int));
  3168.         }
  3169.         break;
  3170.     case 'i':
  3171.         while (len-- > 0) {
  3172.         fromstr = NEXTFROM;
  3173.         aint = SvIV(fromstr);
  3174.         sv_catpvn(cat, (char*)&aint, sizeof(int));
  3175.         }
  3176.         break;
  3177.     case 'N':
  3178.         while (len-- > 0) {
  3179.         fromstr = NEXTFROM;
  3180.         aulong = U_L(SvNV(fromstr));
  3181. #ifdef HAS_HTONL
  3182.         aulong = htonl(aulong);
  3183. #endif
  3184.         sv_catpvn(cat, (char*)&aulong, sizeof(U32));
  3185.         }
  3186.         break;
  3187.     case 'V':
  3188.         while (len-- > 0) {
  3189.         fromstr = NEXTFROM;
  3190.         aulong = U_L(SvNV(fromstr));
  3191. #ifdef HAS_HTOVL
  3192.         aulong = htovl(aulong);
  3193. #endif
  3194.         sv_catpvn(cat, (char*)&aulong, sizeof(U32));
  3195.         }
  3196.         break;
  3197.     case 'L':
  3198.         while (len-- > 0) {
  3199.         fromstr = NEXTFROM;
  3200.         aulong = U_L(SvNV(fromstr));
  3201.         sv_catpvn(cat, (char*)&aulong, sizeof(U32));
  3202.         }
  3203.         break;
  3204.     case 'l':
  3205.         while (len-- > 0) {
  3206.         fromstr = NEXTFROM;
  3207.         along = SvIV(fromstr);
  3208.         sv_catpvn(cat, (char*)&along, sizeof(I32));
  3209.         }
  3210.         break;
  3211. #ifdef HAS_QUAD
  3212.     case 'Q':
  3213.         while (len-- > 0) {
  3214.         fromstr = NEXTFROM;
  3215.         auquad = (unsigned Quad_t)SvIV(fromstr);
  3216.         sv_catpvn(cat, (char*)&auquad, sizeof(unsigned Quad_t));
  3217.         }
  3218.         break;
  3219.     case 'q':
  3220.         while (len-- > 0) {
  3221.         fromstr = NEXTFROM;
  3222.         aquad = (Quad_t)SvIV(fromstr);
  3223.         sv_catpvn(cat, (char*)&aquad, sizeof(Quad_t));
  3224.         }
  3225.         break;
  3226. #endif /* HAS_QUAD */
  3227.     case 'P':
  3228.         len = 1;        /* assume SV is correct length */
  3229.         /* FALL THROUGH */
  3230.     case 'p':
  3231.         while (len-- > 0) {
  3232.         fromstr = NEXTFROM;
  3233.         aptr = SvPV_force(fromstr, na);    /* XXX Error if TEMP? */
  3234.         sv_catpvn(cat, (char*)&aptr, sizeof(char*));
  3235.         }
  3236.         break;
  3237.     case 'u':
  3238.         fromstr = NEXTFROM;
  3239.         aptr = SvPV(fromstr, fromlen);
  3240.         SvGROW(cat, fromlen * 4 / 3);
  3241.         if (len <= 1)
  3242.         len = 45;
  3243.         else
  3244.         len = len / 3 * 3;
  3245.         while (fromlen > 0) {
  3246.         I32 todo;
  3247.  
  3248.         if (fromlen > len)
  3249.             todo = len;
  3250.         else
  3251.             todo = fromlen;
  3252.         doencodes(cat, aptr, todo);
  3253.         fromlen -= todo;
  3254.         aptr += todo;
  3255.         }
  3256.         break;
  3257.     }
  3258.     }
  3259.     SvSETMAGIC(cat);
  3260.     SP = ORIGMARK;
  3261.     PUSHs(cat);
  3262.     RETURN;
  3263. }
  3264. #undef NEXTFROM
  3265.  
  3266. PP(pp_split)
  3267. {
  3268.     dSP; dTARG;
  3269.     AV *ary;
  3270.     register I32 limit = POPi;            /* note, negative is forever */
  3271.     SV *sv = POPs;
  3272.     STRLEN len;
  3273.     register char *s = SvPV(sv, len);
  3274.     char *strend = s + len;
  3275.     register PMOP *pm = (PMOP*)POPs;
  3276.     register SV *dstr;
  3277.     register char *m;
  3278.     I32 iters = 0;
  3279.     I32 maxiters = (strend - s) + 10;
  3280.     I32 i;
  3281.     char *orig;
  3282.     I32 origlimit = limit;
  3283.     I32 realarray = 0;
  3284.     I32 base;
  3285.     AV *oldstack = stack;
  3286.     register REGEXP *rx = pm->op_pmregexp;
  3287.     I32 gimme = GIMME;
  3288.  
  3289.     if (!pm || !s)
  3290.     DIE("panic: do_split");
  3291.     if (pm->op_pmreplroot)
  3292.     ary = GvAVn((GV*)pm->op_pmreplroot);
  3293.     else if (gimme != G_ARRAY)
  3294.     ary = GvAVn(defgv);
  3295.     else
  3296.     ary = Nullav;
  3297.     if (ary && (gimme != G_ARRAY || (pm->op_pmflags & PMf_ONCE))) {
  3298.     realarray = 1;
  3299.     if (!AvREAL(ary)) {
  3300.         AvREAL_on(ary);
  3301.         for (i = AvFILL(ary); i >= 0; i--)
  3302.         AvARRAY(ary)[i] = &sv_undef;    /* don't free mere refs */
  3303.     }
  3304.     av_extend(ary,0);
  3305.     av_clear(ary);
  3306.     /* temporarily switch stacks */
  3307.     SWITCHSTACK(stack, ary);
  3308.     }
  3309.     base = SP - stack_base;
  3310.     orig = s;
  3311.     if (pm->op_pmflags & PMf_SKIPWHITE) {
  3312.     while (isSPACE(*s))
  3313.         s++;
  3314.     }
  3315.     if (!limit)
  3316.     limit = maxiters + 2;
  3317.     if (pm->op_pmflags & PMf_WHITE) {
  3318.     while (--limit) {
  3319.         /*SUPPRESS 530*/
  3320.         for (m = s; m < strend && !isSPACE(*m); m++) ;
  3321.         if (m >= strend)
  3322.         break;
  3323.         dstr = NEWSV(30, m-s);
  3324.         sv_setpvn(dstr, s, m-s);
  3325.         if (!realarray)
  3326.         sv_2mortal(dstr);
  3327.         XPUSHs(dstr);
  3328.         /*SUPPRESS 530*/
  3329.         for (s = m + 1; s < strend && isSPACE(*s); s++) ;
  3330.     }
  3331.     }
  3332.     else if (strEQ("^", rx->precomp)) {
  3333.     while (--limit) {
  3334.         /*SUPPRESS 530*/
  3335.         for (m = s; m < strend && *m != '\n'; m++) ;
  3336.         m++;
  3337.         if (m >= strend)
  3338.         break;
  3339.         dstr = NEWSV(30, m-s);
  3340.         sv_setpvn(dstr, s, m-s);
  3341.         if (!realarray)
  3342.         sv_2mortal(dstr);
  3343.         XPUSHs(dstr);
  3344.         s = m;
  3345.     }
  3346.     }
  3347.     else if (pm->op_pmshort) {
  3348.     i = SvCUR(pm->op_pmshort);
  3349.     if (i == 1) {
  3350.         I32 fold = (pm->op_pmflags & PMf_FOLD);
  3351.         i = *SvPVX(pm->op_pmshort);
  3352.         if (fold && isUPPER(i))
  3353.         i = toLOWER(i);
  3354.         while (--limit) {
  3355.         if (fold) {
  3356.             for ( m = s;
  3357.               m < strend && *m != i &&
  3358.                 (!isUPPER(*m) || toLOWER(*m) != i);
  3359.               m++)            /*SUPPRESS 530*/
  3360.             ;
  3361.         }
  3362.         else                /*SUPPRESS 530*/
  3363.             for (m = s; m < strend && *m != i; m++) ;
  3364.         if (m >= strend)
  3365.             break;
  3366.         dstr = NEWSV(30, m-s);
  3367.         sv_setpvn(dstr, s, m-s);
  3368.         if (!realarray)
  3369.             sv_2mortal(dstr);
  3370.         XPUSHs(dstr);
  3371.         s = m + 1;
  3372.         }
  3373.     }
  3374.     else {
  3375. #ifndef lint
  3376.         while (s < strend && --limit &&
  3377.           (m=fbm_instr((unsigned char*)s, (unsigned char*)strend,
  3378.             pm->op_pmshort)) )
  3379. #endif
  3380.         {
  3381.         dstr = NEWSV(31, m-s);
  3382.         sv_setpvn(dstr, s, m-s);
  3383.         if (!realarray)
  3384.             sv_2mortal(dstr);
  3385.         XPUSHs(dstr);
  3386.         s = m + i;
  3387.         }
  3388.     }
  3389.     }
  3390.     else {
  3391.     maxiters += (strend - s) * rx->nparens;
  3392.     while (s < strend && --limit &&
  3393.         regexec(rx, s, strend, orig, 1, Nullsv, TRUE) ) {
  3394.         if (rx->subbase
  3395.           && rx->subbase != orig) {
  3396.         m = s;
  3397.         s = orig;
  3398.         orig = rx->subbase;
  3399.         s = orig + (m - s);
  3400.         strend = s + (strend - m);
  3401.         }
  3402.         m = rx->startp[0];
  3403.         dstr = NEWSV(32, m-s);
  3404.         sv_setpvn(dstr, s, m-s);
  3405.         if (!realarray)
  3406.         sv_2mortal(dstr);
  3407.         XPUSHs(dstr);
  3408.         if (rx->nparens) {
  3409.         for (i = 1; i <= rx->nparens; i++) {
  3410.             s = rx->startp[i];
  3411.             m = rx->endp[i];
  3412.             if (m && s) {
  3413.             dstr = NEWSV(33, m-s);
  3414.             sv_setpvn(dstr, s, m-s);
  3415.             }
  3416.             else
  3417.             dstr = NEWSV(33, 0);
  3418.             if (!realarray)
  3419.             sv_2mortal(dstr);
  3420.             XPUSHs(dstr);
  3421.         }
  3422.         }
  3423.         s = rx->endp[0];
  3424.     }
  3425.     }
  3426.     iters = (SP - stack_base) - base;
  3427.     if (iters > maxiters)
  3428.     DIE("Split loop");
  3429.     
  3430.     /* keep field after final delim? */
  3431.     if (s < strend || (iters && origlimit)) {
  3432.     dstr = NEWSV(34, strend-s);
  3433.     sv_setpvn(dstr, s, strend-s);
  3434.     if (!realarray)
  3435.         sv_2mortal(dstr);
  3436.     XPUSHs(dstr);
  3437.     iters++;
  3438.     }
  3439.     else if (!origlimit) {
  3440.     while (iters > 0 && SvCUR(TOPs) == 0)
  3441.         iters--, SP--;
  3442.     }
  3443.     if (realarray) {
  3444.     SWITCHSTACK(ary, oldstack);
  3445.     if (gimme == G_ARRAY) {
  3446.         EXTEND(SP, iters);
  3447.         Copy(AvARRAY(ary), SP + 1, iters, SV*);
  3448.         SP += iters;
  3449.         RETURN;
  3450.     }
  3451.     }
  3452.     else {
  3453.     if (gimme == G_ARRAY)
  3454.         RETURN;
  3455.     }
  3456.     if (iters || !pm->op_pmreplroot) {
  3457.     GETTARGET;
  3458.     PUSHi(iters);
  3459.     RETURN;
  3460.     }
  3461.     RETPUSHUNDEF;
  3462. }
  3463.  
  3464.